@tiledesk/tiledesk-server 2.17.4 → 2.18.3
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 +8 -3
- package/app.js +4 -0
- package/channels/chat21/chat21WebHook.js +6 -1
- package/docs/routes-answered.md +153 -0
- package/event/authEvent.js +16 -0
- package/event/projectUserEvent.js +39 -0
- package/event/roleEvent.js +9 -0
- package/middleware/has-role.js +160 -121
- package/middleware/passport.js +180 -179
- package/migrations/1757601159298-project_user_role_type.js +104 -0
- package/models/department.js +3 -0
- package/models/groupMemberSchama.js +19 -0
- package/models/kb_setting.js +74 -4
- package/models/permissionConstants.js +19 -0
- package/models/project_user.js +86 -8
- package/models/request.js +1 -0
- package/models/role.js +31 -0
- package/models/roleConstants.js +2 -0
- package/package.json +1 -1
- package/pubmodules/analytics/analytics.js +2 -2
- package/pubmodules/cache/mongoose-cachegoose-fn.js +37 -0
- package/pubmodules/canned/cannedResponseRoute.js +34 -6
- package/pubmodules/routing-queue/listener.js +7 -1
- package/pubmodules/trigger/rulesTrigger.js +1 -6
- package/routes/answered.js +227 -0
- package/routes/auth.js +3 -1
- package/routes/department.js +7 -1
- package/routes/message.js +4 -1
- package/routes/project.js +41 -3
- package/routes/project_user.js +62 -11
- package/routes/request.js +32 -30
- package/routes/roles.js +151 -0
- package/routes/unanswered.js +32 -19
- package/routes/widget.js +3 -1
- package/services/cacheEnabler.js +5 -8
- package/services/departmentService.js +39 -11
- package/services/emailService.js +2 -2
- package/services/pendingInvitationService.js +2 -0
- package/services/projectService.js +3 -1
- package/services/projectUserService.js +67 -4
- package/services/subscriptionNotifierQueued.js +8 -0
- package/services/updateRequestSnapshotQueued.js +0 -3
- package/test/departmentService.js +5 -0
- package/test/messageRoute.js +7 -4
- package/test/projectUserRoute.js +116 -0
- package/test/requestService.js +7 -3
- package/test-int/bot.js +3 -2
- package/websocket/webSocketServer.js +273 -225
- package/routes/auth_newjwt.js +0 -648
package/models/project_user.js
CHANGED
|
@@ -31,6 +31,10 @@ var TagSchema = require("../models/tag");
|
|
|
31
31
|
index: true
|
|
32
32
|
// required: true
|
|
33
33
|
},
|
|
34
|
+
roleType: {
|
|
35
|
+
type: Number, //1 for agents 2 for users
|
|
36
|
+
index: true
|
|
37
|
+
},
|
|
34
38
|
user_available: {
|
|
35
39
|
type: Boolean,
|
|
36
40
|
default: true,
|
|
@@ -63,6 +67,7 @@ var TagSchema = require("../models/tag");
|
|
|
63
67
|
type: Object,
|
|
64
68
|
},
|
|
65
69
|
tags: [TagSchema],
|
|
70
|
+
permissions: [String],
|
|
66
71
|
createdBy: {
|
|
67
72
|
type: String,
|
|
68
73
|
required: true
|
|
@@ -86,14 +91,16 @@ var TagSchema = require("../models/tag");
|
|
|
86
91
|
);
|
|
87
92
|
|
|
88
93
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
94
|
+
|
|
95
|
+
//TODO COMMENT IT unused. Now events are not saved to the db
|
|
96
|
+
// Project_userSchema.virtual('events', {
|
|
97
|
+
// ref: 'event', // The model to use
|
|
98
|
+
// localField: '_id', // Find people where `localField`
|
|
99
|
+
// foreignField: 'project_user', // is equal to `foreignField`
|
|
100
|
+
// justOne: false,
|
|
101
|
+
// // options: { getters: true }
|
|
102
|
+
// options: { sort: { createdAt: -1 }, limit: 5 } // Query options, see http://bit.ly/mongoose-query-options
|
|
103
|
+
// });
|
|
97
104
|
|
|
98
105
|
Project_userSchema.virtual('isAuthenticated').get(function () {
|
|
99
106
|
if (this.role === RoleConstants.GUEST ) {
|
|
@@ -103,6 +110,77 @@ Project_userSchema.virtual('isAuthenticated').get(function () {
|
|
|
103
110
|
}
|
|
104
111
|
});
|
|
105
112
|
|
|
113
|
+
Project_userSchema.methods.getAllPermissions = function () {
|
|
114
|
+
// console.log("this", this);
|
|
115
|
+
winston.debug("this.permissions", this.permissions);
|
|
116
|
+
|
|
117
|
+
// console.log("this.rolePermissions", this.rolePermissions);
|
|
118
|
+
winston.debug("this._doc.rolePermissions", this._doc.rolePermissions);
|
|
119
|
+
|
|
120
|
+
let all = this.permissions;
|
|
121
|
+
|
|
122
|
+
if (this._doc.rolePermissions) {
|
|
123
|
+
all = [...new Set([...this.permissions, ...this._doc.rolePermissions])]; //https://medium.com/@rivoltafilippo/javascript-merge-arrays-without-duplicates-3fbd8f4881be
|
|
124
|
+
}
|
|
125
|
+
// const all = this.permissions.concat(this._doc.rolePermissions);
|
|
126
|
+
winston.verbose("getAllPermissions all", all);
|
|
127
|
+
|
|
128
|
+
return all;
|
|
129
|
+
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
Project_userSchema.methods.hasPermissionOrRole = function (permission, roles) {
|
|
135
|
+
var all_permissions = this.getAllPermissions();
|
|
136
|
+
// var all_permissions = this.getAllPermissions();
|
|
137
|
+
// console.log("hasPermissionOrRole", all_permissions, permission, this.role, roles)
|
|
138
|
+
if (all_permissions && all_permissions.length>0 ) {
|
|
139
|
+
if (all_permissions.includes(permission)) {
|
|
140
|
+
// console.log("hasPermissionOrRole found", permission)
|
|
141
|
+
return true;
|
|
142
|
+
} else {
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
}else {
|
|
146
|
+
if (roles instanceof Array) {
|
|
147
|
+
// console.log("hasPermissionOrRole roles instanceof Array");
|
|
148
|
+
for (var i = 0; i < roles.length; i++) {
|
|
149
|
+
if (roles[i]==this.role) {
|
|
150
|
+
return true;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return false;
|
|
154
|
+
|
|
155
|
+
} else {
|
|
156
|
+
// console.log("roles instanceof ", roles instanceof );
|
|
157
|
+
// console.log("this.role instanceof ", this.role instanceof );
|
|
158
|
+
|
|
159
|
+
// console.log("hasPermissionOrRole role ", this.role, roles);
|
|
160
|
+
if (this.role==roles) {
|
|
161
|
+
// console.log("role ok");
|
|
162
|
+
return true;
|
|
163
|
+
} else {
|
|
164
|
+
// console.log("role ko");
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
Project_userSchema.methods.hasPermission = function (permission) {
|
|
174
|
+
if (this.permissions && this.permissions.length>0 ) {
|
|
175
|
+
if (this.permissions.includes(permission)) {
|
|
176
|
+
return true;
|
|
177
|
+
} else {
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
}else {
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
106
184
|
|
|
107
185
|
|
|
108
186
|
// var query = { id_project: req.params.projectid, id_user: req.user._id};
|
package/models/request.js
CHANGED
|
@@ -11,6 +11,7 @@ var ProjectUserSchema = require("../models/project_user").schema;
|
|
|
11
11
|
var RequestStatus = require("../models/requestStatus");
|
|
12
12
|
var LeadSchema = require("../models/lead").schema; //it's not used but i you run test like (mocha departmentService.js) it throws this not blocking exception: error: error getting requestSchema hasn't been registered for model "lead".
|
|
13
13
|
var NoteSchema = require("../models/note").schema;
|
|
14
|
+
|
|
14
15
|
var TagSchema = require("../models/tag");
|
|
15
16
|
var LocationSchema = require("../models/location");
|
|
16
17
|
var RequestSnapshotSchema = require("../models/requestSnapshot");
|
package/models/role.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
var mongoose = require('mongoose');
|
|
2
|
+
var Schema = mongoose.Schema;
|
|
3
|
+
var winston = require('../config/winston');
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
var RoleSchema = new Schema({
|
|
7
|
+
name: {
|
|
8
|
+
type: String,
|
|
9
|
+
required: true,
|
|
10
|
+
index:true
|
|
11
|
+
},
|
|
12
|
+
permissions: [String],
|
|
13
|
+
// permissions: {
|
|
14
|
+
// type: String,
|
|
15
|
+
// required: true
|
|
16
|
+
// },
|
|
17
|
+
id_project: {
|
|
18
|
+
type: String,
|
|
19
|
+
required: true,
|
|
20
|
+
index: true
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
});
|
|
24
|
+
var role = mongoose.model('role', RoleSchema);
|
|
25
|
+
|
|
26
|
+
if (process.env.MONGOOSE_SYNCINDEX) {
|
|
27
|
+
role.syncIndexes();
|
|
28
|
+
winston.verbose("role syncIndexes")
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
module.exports = role;
|
package/models/roleConstants.js
CHANGED
package/package.json
CHANGED
|
@@ -1780,7 +1780,7 @@ router.get('/tags/:type', async (req, res) => {
|
|
|
1780
1780
|
date: { $gte: startDate, $lte: endDate }
|
|
1781
1781
|
}
|
|
1782
1782
|
|
|
1783
|
-
|
|
1783
|
+
winston.debug("analytics tags query: ", query)
|
|
1784
1784
|
|
|
1785
1785
|
let result = await Analytics.find(query).catch((err) => {
|
|
1786
1786
|
winston.error("Error finding Analytics: ", err);
|
|
@@ -1821,7 +1821,7 @@ router.get('/tags/:type', async (req, res) => {
|
|
|
1821
1821
|
|
|
1822
1822
|
// Assembly final result
|
|
1823
1823
|
let data = { dates, series };
|
|
1824
|
-
|
|
1824
|
+
|
|
1825
1825
|
|
|
1826
1826
|
return res.status(200).send(data);
|
|
1827
1827
|
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
var triggerEventEmitter = require("../trigger/event/triggerEventEmitter");
|
|
12
12
|
var subscriptionEvent = require("../../event/subscriptionEvent");
|
|
13
|
+
var roleEvent = require("../../event/roleEvent");
|
|
13
14
|
|
|
14
15
|
var winston = require('../../config/winston');
|
|
15
16
|
|
|
@@ -837,7 +838,43 @@
|
|
|
837
838
|
});
|
|
838
839
|
});
|
|
839
840
|
});
|
|
841
|
+
|
|
842
|
+
|
|
843
|
+
roleEvent.on('role.create', function(role) {
|
|
844
|
+
setImmediate(() => {
|
|
845
|
+
var key =role.id_project+":roles:"+role.name;
|
|
846
|
+
winston.verbose("Deleting cache for role.create with key: " + key);
|
|
847
|
+
winston.verbose("Creating cache for department.create with key: " + key);
|
|
848
|
+
client.set(key, role, cacheUtil.defaultTTL, (err, reply) => {
|
|
849
|
+
winston.debug("Created cache for role.create",reply);
|
|
850
|
+
winston.verbose("Created cache for role.create",{err:err});
|
|
851
|
+
});
|
|
852
|
+
|
|
853
|
+
});
|
|
854
|
+
});
|
|
855
|
+
|
|
856
|
+
roleEvent.on('role.update', function(role) {
|
|
857
|
+
setImmediate(() => {
|
|
858
|
+
var key =role.id_project+":roles:"+role.name;
|
|
859
|
+
winston.verbose("Deleting cache for role.update with key: " + key);
|
|
860
|
+
client.set(key, role, cacheUtil.defaultTTL, (err, reply) => {
|
|
861
|
+
winston.debug("Updated cache for role.update",reply);
|
|
862
|
+
winston.verbose("Updated cache for role.update",{err:err});
|
|
863
|
+
});
|
|
864
|
+
});
|
|
865
|
+
});
|
|
840
866
|
|
|
867
|
+
roleEvent.on("role.delete", function(role) {
|
|
868
|
+
setImmediate(() => {
|
|
869
|
+
var key =role.id_project+":roles:"+role.name;
|
|
870
|
+
winston.verbose("Deleting cache for role.delete with key: " + key);
|
|
871
|
+
del(client._cache._engine.client, key, function (err, reply) {
|
|
872
|
+
winston.debug("Deleted cache for role.delete",reply);
|
|
873
|
+
winston.verbose("Deleted cache for role.delete",{err:err});
|
|
874
|
+
});
|
|
875
|
+
});
|
|
876
|
+
});
|
|
877
|
+
|
|
841
878
|
}
|
|
842
879
|
|
|
843
880
|
|
|
@@ -3,6 +3,7 @@ var router = express.Router();
|
|
|
3
3
|
var CannedResponse = require("./cannedResponse");
|
|
4
4
|
var winston = require('../../config/winston');
|
|
5
5
|
const RoleConstants = require('../../models/roleConstants');
|
|
6
|
+
const roleConstants = require('../../models/roleConstants');
|
|
6
7
|
// const CannedResponseEvent = require('../event/CannedResponseEvent');
|
|
7
8
|
|
|
8
9
|
|
|
@@ -16,13 +17,18 @@ router.post('/', function (req, res) {
|
|
|
16
17
|
text: req.body.text,
|
|
17
18
|
id_project: req.projectid,
|
|
18
19
|
createdBy: req.user.id,
|
|
19
|
-
updatedBy: req.user.id
|
|
20
|
+
updatedBy: req.user.id,
|
|
21
|
+
shared: false
|
|
20
22
|
});
|
|
21
23
|
|
|
22
24
|
if (req.projectuser.role == 'owner' || req.projectuser.role == 'admin') {
|
|
23
25
|
newCannedResponse.shared = true;
|
|
24
26
|
} else {
|
|
25
|
-
|
|
27
|
+
if (req.projectuser.roleType === roleConstants.TYPE_AGENTS) {
|
|
28
|
+
if (req.body.shared && req.body.shared === true) {
|
|
29
|
+
newCannedResponse.shared = true;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
26
32
|
}
|
|
27
33
|
|
|
28
34
|
newCannedResponse.save(function (err, savedCannedResponse) {
|
|
@@ -40,8 +46,8 @@ router.put('/:cannedResponseid', async function (req, res) {
|
|
|
40
46
|
winston.debug(req.body);
|
|
41
47
|
const canned_id = req.params.cannedResponseid;
|
|
42
48
|
const id_project = req.projectid;
|
|
43
|
-
let user_role = req.projectuser
|
|
44
|
-
|
|
49
|
+
let user_role = req.projectuser?.role;
|
|
50
|
+
let roleType = req.projectuser?.roleType || null;
|
|
45
51
|
var update = {};
|
|
46
52
|
|
|
47
53
|
const allowedFields = ['title', 'text', 'attributes']
|
|
@@ -79,6 +85,12 @@ router.put('/:cannedResponseid', async function (req, res) {
|
|
|
79
85
|
winston.warn("Not allowed. User " + req.user.id + " can't modify a canned response of user " + canned.createdBy);
|
|
80
86
|
return res.status(403).send({ success: false, error: "Not allowed to modify a non administration canned response"})
|
|
81
87
|
}
|
|
88
|
+
}
|
|
89
|
+
else if (roleType === RoleConstants.TYPE_AGENTS) {
|
|
90
|
+
if (canned.hasOwnProperty('shared') && canned.shared === false && canned.createdBy !== req.user.id) {
|
|
91
|
+
winston.warn("Not allowed. User " + req.user.id + " can't modify a canned response of user " + canned.createdBy);
|
|
92
|
+
return res.status(403).send({ success: false, error: "Not allowed to modify a non administration canned response"})
|
|
93
|
+
}
|
|
82
94
|
} else {
|
|
83
95
|
winston.warn("User " + req.user.id + "trying to modify canned with role " + user_role);
|
|
84
96
|
return res.status(401).send({ success: false, error: "Unauthorized"})
|
|
@@ -100,6 +112,7 @@ router.delete('/:cannedResponseid', async function (req, res) {
|
|
|
100
112
|
const canned_id = req.params.cannedResponseid;
|
|
101
113
|
const id_project = req.projectid;
|
|
102
114
|
let user_role = req.projectuser.role;
|
|
115
|
+
let roleType = req.projectuser?.roleType || null;
|
|
103
116
|
|
|
104
117
|
let canned = await CannedResponse.findOne({ _id: canned_id, id_project: id_project }).catch((err) => {
|
|
105
118
|
winston.error("Error finding canned response: ", err);
|
|
@@ -128,7 +141,14 @@ router.delete('/:cannedResponseid', async function (req, res) {
|
|
|
128
141
|
winston.warn("Not allowed. User " + req.user.id + " can't delete a canned response of user " + canned.createdBy);
|
|
129
142
|
return res.status(403).send({ success: false, error: "Not allowed to delete a non administration canned response"})
|
|
130
143
|
}
|
|
131
|
-
}
|
|
144
|
+
}
|
|
145
|
+
else if (roleType === RoleConstants.TYPE_AGENTS) {
|
|
146
|
+
if (canned.hasOwnProperty('shared') && canned.shared === false && canned.createdBy !== req.user.id) {
|
|
147
|
+
winston.warn("Not allowed. User " + req.user.id + " can't delete a canned response of user " + canned.createdBy);
|
|
148
|
+
return res.status(403).send({ success: false, error: "Not allowed to delete a non administration canned response"})
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
132
152
|
winston.warn("User " + req.user.id + "trying to delete canned with role " + user_role);
|
|
133
153
|
return res.status(401).send({ success: false, error: "Unauthorized"})
|
|
134
154
|
}
|
|
@@ -149,6 +169,7 @@ router.delete('/:cannedResponseid/physical', async function (req, res) {
|
|
|
149
169
|
const canned_id = req.params.cannedResponseid;
|
|
150
170
|
const id_project = req.projectid;
|
|
151
171
|
let user_role = req.projectuser.role;
|
|
172
|
+
let roleType = req.projectuser?.roleType || null;
|
|
152
173
|
|
|
153
174
|
let canned = await CannedResponse.findOne({ _id: canned_id, id_project: id_project }).catch((err) => {
|
|
154
175
|
winston.error("Error finding canned response: ", err);
|
|
@@ -177,7 +198,14 @@ router.delete('/:cannedResponseid/physical', async function (req, res) {
|
|
|
177
198
|
winston.warn("Not allowed. User " + req.user.id + " can't delete a canned response of user " + canned.createdBy);
|
|
178
199
|
return res.status(403).send({ success: false, error: "Not allowed to delete a non administration canned response"})
|
|
179
200
|
}
|
|
180
|
-
}
|
|
201
|
+
}
|
|
202
|
+
else if (roleType === RoleConstants.TYPE_AGENTS) {
|
|
203
|
+
if (canned.hasOwnProperty('shared') && canned.shared === false && canned.createdBy !== req.user.id) {
|
|
204
|
+
winston.warn("Not allowed. User " + req.user.id + " can't delete a canned response of user " + canned.createdBy);
|
|
205
|
+
return res.status(403).send({ success: false, error: "Not allowed to delete a non administration canned response"})
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
181
209
|
winston.warn("User " + req.user.id + "trying to delete canned with role " + user_role);
|
|
182
210
|
return res.status(401).send({ success: false, error: "Unauthorized"})
|
|
183
211
|
}
|
|
@@ -110,7 +110,13 @@ class Listener {
|
|
|
110
110
|
var query = {id_project: operatorsResult.id_project, status: {$lt:1000}};
|
|
111
111
|
// asyncForEach(operatorsResult.available_agents, async (aa) => {
|
|
112
112
|
for (const aa of operatorsResult.available_agents) {
|
|
113
|
-
|
|
113
|
+
let user_id;
|
|
114
|
+
if (aa.id_user._id) {
|
|
115
|
+
user_id = aa.id_user._id.toString();// attento qui
|
|
116
|
+
} else {
|
|
117
|
+
user_id = aa.id_user;// attento qui
|
|
118
|
+
}
|
|
119
|
+
query.participants = user_id;
|
|
114
120
|
winston.debug("department operators query:" , query);
|
|
115
121
|
|
|
116
122
|
|
|
@@ -1164,11 +1164,8 @@ class RulesTrigger {
|
|
|
1164
1164
|
lead: createdLead, requester: puser
|
|
1165
1165
|
};
|
|
1166
1166
|
|
|
1167
|
-
|
|
1167
|
+
|
|
1168
1168
|
return requestService.create(new_request).then(function (savedRequest) {
|
|
1169
|
-
//console.log("[Performance] (rulesTrigger) requestService.create time: " + (Date.now() - t1));
|
|
1170
|
-
// performance console log
|
|
1171
|
-
// console.log("************* request created trigger: "+new Date().toISOString());
|
|
1172
1169
|
|
|
1173
1170
|
if (attributes) {
|
|
1174
1171
|
attributes.sendnotification = false; // sembra nn funzionae
|
|
@@ -1177,9 +1174,7 @@ class RulesTrigger {
|
|
|
1177
1174
|
var senderFullname = fullname || 'Guest'; // guest_here
|
|
1178
1175
|
|
|
1179
1176
|
// create(sender, senderFullname, recipient, text, id_project, createdBy, status, attributes, type, metadata, language) {
|
|
1180
|
-
//let t2 = Date.now();
|
|
1181
1177
|
return messageService.create( id_user, senderFullname , savedRequest.request_id, text, id_project, id_user, MessageConstants.CHAT_MESSAGE_STATUS.SENDING, attributes, type, eventTrigger.event.metadata, language).then(function(savedMessage) {
|
|
1182
|
-
//console.log("[Performance] (rulesTrigger) messageService.create time: " + (Date.now() - t2));
|
|
1183
1178
|
return savedMessage;
|
|
1184
1179
|
});
|
|
1185
1180
|
}).catch(function (err) {
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
const express = require('express');
|
|
2
|
+
const router = express.Router();
|
|
3
|
+
const { Namespace, AnsweredQuestion } = require('../models/kb_setting');
|
|
4
|
+
const winston = require('../config/winston');
|
|
5
|
+
|
|
6
|
+
// Add a new unanswerd question
|
|
7
|
+
router.post('/', async (req, res) => {
|
|
8
|
+
try {
|
|
9
|
+
const { namespace, question, answer, tokens, request_id } = req.body;
|
|
10
|
+
const id_project = req.projectid;
|
|
11
|
+
|
|
12
|
+
if (!namespace || !question || !answer) {
|
|
13
|
+
return res.status(400).json({
|
|
14
|
+
success: false,
|
|
15
|
+
error: "Missing required parameters: namespace, question and answer"
|
|
16
|
+
})
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Check if namespae belongs to project
|
|
20
|
+
const isValidNamespace = await validateNamespace(id_project, namespace);
|
|
21
|
+
if (!isValidNamespace) {
|
|
22
|
+
return res.status(403).json({
|
|
23
|
+
success: false,
|
|
24
|
+
error: "Not allowed. The namespace does not belong to the current project."
|
|
25
|
+
})
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const answeredQuestion = new AnsweredQuestion({
|
|
29
|
+
id_project,
|
|
30
|
+
namespace,
|
|
31
|
+
question,
|
|
32
|
+
answer,
|
|
33
|
+
tokens,
|
|
34
|
+
request_id,
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const savedQuestion = await answeredQuestion.save();
|
|
38
|
+
res.status(200).json(savedQuestion);
|
|
39
|
+
|
|
40
|
+
} catch (error) {
|
|
41
|
+
winston.error('Error adding answered question:', error);
|
|
42
|
+
res.status(500).json({
|
|
43
|
+
success: false,
|
|
44
|
+
error: "Error adding answered question"
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
// Get all answered questions for a namespace
|
|
50
|
+
router.get('/:namespace', async (req, res) => {
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
const { namespace } = req.params;
|
|
54
|
+
const id_project = req.projectid;
|
|
55
|
+
|
|
56
|
+
if (!namespace) {
|
|
57
|
+
return res.status(400).json({
|
|
58
|
+
success: false,
|
|
59
|
+
error: "Missing required parameter: namespace"
|
|
60
|
+
})
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Check if namespace belongs to project
|
|
64
|
+
const isValidNamespace = await validateNamespace(id_project, namespace);
|
|
65
|
+
if (!isValidNamespace) {
|
|
66
|
+
return res.status(403).json({
|
|
67
|
+
success: false,
|
|
68
|
+
error: "Not allowed. The namespace does not belong to the current project."
|
|
69
|
+
})
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const page = parseInt(req.query.page) || 0;
|
|
73
|
+
const limit = parseInt(req.query.limit) || 20;
|
|
74
|
+
const sortField = req.query.sortField || 'created_at';
|
|
75
|
+
const direction = parseInt(req.query.direction) || -1;
|
|
76
|
+
|
|
77
|
+
const filter = { id_project, namespace };
|
|
78
|
+
|
|
79
|
+
let projection = undefined;
|
|
80
|
+
|
|
81
|
+
if (req.query.search) {
|
|
82
|
+
filter.$text = { $search: req.query.search };
|
|
83
|
+
// Add score to projection if it's a text search
|
|
84
|
+
projection = { score: { $meta: "textScore" } };
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
let sortObj;
|
|
88
|
+
if (projection && projection.score) {
|
|
89
|
+
sortObj = { score: { $meta: "textScore" } };
|
|
90
|
+
} else {
|
|
91
|
+
sortObj = { [sortField]: direction };
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const questions = await AnsweredQuestion.find(filter, projection)
|
|
95
|
+
.sort(sortObj)
|
|
96
|
+
.skip(page * limit)
|
|
97
|
+
.limit(limit);
|
|
98
|
+
|
|
99
|
+
const count = await AnsweredQuestion.countDocuments(filter);
|
|
100
|
+
|
|
101
|
+
res.status(200).json({
|
|
102
|
+
count,
|
|
103
|
+
questions,
|
|
104
|
+
query: {
|
|
105
|
+
page,
|
|
106
|
+
limit,
|
|
107
|
+
sortField,
|
|
108
|
+
direction,
|
|
109
|
+
search: req.query.search || undefined
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
} catch (error) {
|
|
114
|
+
winston.error('Error getting answered questions:', error);
|
|
115
|
+
res.status(500).json({
|
|
116
|
+
success: false,
|
|
117
|
+
error: "Error getting answered questions"
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
router.delete('/:id', async (req, res) => {
|
|
124
|
+
try {
|
|
125
|
+
const { id } = req.params;
|
|
126
|
+
const id_project = req.projectid;
|
|
127
|
+
|
|
128
|
+
const deleted = await AnsweredQuestion.findOneAndDelete({ _id: id, id_project });
|
|
129
|
+
if (!deleted) {
|
|
130
|
+
return res.status(404).json({
|
|
131
|
+
success: false,
|
|
132
|
+
error: "Question not found"
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
res.status(200).json({
|
|
137
|
+
success: true,
|
|
138
|
+
message: "Question deleted successfully"
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
} catch (error) {
|
|
142
|
+
winston.error('Error deleting answered question:', error);
|
|
143
|
+
res.status(500).json({
|
|
144
|
+
success: false,
|
|
145
|
+
error: "Error deleting answered question"
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
router.delete('/namespace/:namespace', async (req, res) => {
|
|
151
|
+
try {
|
|
152
|
+
const { namespace } = req.params;
|
|
153
|
+
const id_project = req.projectid;
|
|
154
|
+
|
|
155
|
+
// Check if namespace belongs to project
|
|
156
|
+
const isValidNamespace = await validateNamespace(id_project, namespace);
|
|
157
|
+
if (!isValidNamespace) {
|
|
158
|
+
return res.status(403).json({
|
|
159
|
+
success: false,
|
|
160
|
+
error: "Not allowed. The namespace does not belong to the current project."
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const result = await AnsweredQuestion.deleteMany({ id_project, namespace });
|
|
165
|
+
res.status(200).json({
|
|
166
|
+
success: true,
|
|
167
|
+
count: result.deletedCount,
|
|
168
|
+
message: "All questions deleted successfully"
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
} catch (error) {
|
|
172
|
+
winston.error('Error deleting answered questions:', error);
|
|
173
|
+
res.status(500).json({
|
|
174
|
+
success: false,
|
|
175
|
+
error: "Error deleting answered questions"
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
router.get('/count/:namespace', async (req, res) => {
|
|
181
|
+
try {
|
|
182
|
+
const { namespace } = req.params;
|
|
183
|
+
const id_project = req.projectid;
|
|
184
|
+
|
|
185
|
+
if (!namespace) {
|
|
186
|
+
return res.status(400).json({
|
|
187
|
+
success: false,
|
|
188
|
+
error: "Missing required parameter: namespace"
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Check if namespace belongs to project
|
|
193
|
+
const isValidNamespace = await validateNamespace(id_project, namespace);
|
|
194
|
+
if (!isValidNamespace) {
|
|
195
|
+
return res.status(403).json({
|
|
196
|
+
success: false,
|
|
197
|
+
error: "Not allowed. The namespace does not belong to the current project."
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const count = await AnsweredQuestion.countDocuments({ id_project, namespace });
|
|
202
|
+
res.status(200).json({ count });
|
|
203
|
+
|
|
204
|
+
} catch (error) {
|
|
205
|
+
winston.error('Error counting answered questions:', error);
|
|
206
|
+
res.status(500).json({
|
|
207
|
+
success: false,
|
|
208
|
+
error: "Error counting answered questions"
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
})
|
|
212
|
+
|
|
213
|
+
// Helper function to validate namespace
|
|
214
|
+
async function validateNamespace(id_project, namespace_id) {
|
|
215
|
+
try {
|
|
216
|
+
const namespace = await Namespace.findOne({
|
|
217
|
+
id_project: id_project,
|
|
218
|
+
id: namespace_id
|
|
219
|
+
});
|
|
220
|
+
return !!namespace;
|
|
221
|
+
} catch (err) {
|
|
222
|
+
winston.error('validate namespace error: ', err);
|
|
223
|
+
throw err;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
module.exports = router;
|
package/routes/auth.js
CHANGED
|
@@ -197,6 +197,7 @@ function (req, res) {
|
|
|
197
197
|
id_project: req.body.id_project, //attentoqui
|
|
198
198
|
uuid_user: req.user._id,
|
|
199
199
|
role: RoleConstants.GUEST,
|
|
200
|
+
roleType : RoleConstants.TYPE_USERS,
|
|
200
201
|
user_available: true,
|
|
201
202
|
createdBy: req.user._id,
|
|
202
203
|
updatedBy: req.user._id
|
|
@@ -408,6 +409,7 @@ router.post('/signinWithCustomToken', [
|
|
|
408
409
|
uuid_user: req.user._id,
|
|
409
410
|
// id_user: req.user._id,
|
|
410
411
|
role: role,
|
|
412
|
+
roleType : RoleConstants.TYPE_USERS, //RICONtROLLA QUIA
|
|
411
413
|
user_available: true,
|
|
412
414
|
createdBy: req.user._id, //oppure req.user.id attento problema
|
|
413
415
|
updatedBy: req.user._id
|
|
@@ -486,7 +488,7 @@ router.post('/signinWithCustomToken', [
|
|
|
486
488
|
} else {
|
|
487
489
|
winston.debug('different role : '+role + " " + project_user.role);
|
|
488
490
|
}
|
|
489
|
-
|
|
491
|
+
// rolecheck
|
|
490
492
|
if (req.user.role && (req.user.role === RoleConstants.OWNER || req.user.role === RoleConstants.ADMIN || req.user.role === RoleConstants.AGENT)) {
|
|
491
493
|
let userFromDB = await User.findOne({email: req.user.email.toLowerCase(), status: 100}).exec();
|
|
492
494
|
|
package/routes/department.js
CHANGED
|
@@ -24,6 +24,7 @@ router.post('/', [passport.authenticate(['basic', 'jwt'], { session: false }), v
|
|
|
24
24
|
default: req.body.default,
|
|
25
25
|
status: req.body.status,
|
|
26
26
|
id_group: req.body.id_group,
|
|
27
|
+
groups: req.body.groups,
|
|
27
28
|
id_project: req.projectid,
|
|
28
29
|
createdBy: req.user.id,
|
|
29
30
|
updatedBy: req.user.id
|
|
@@ -79,7 +80,9 @@ router.put('/:departmentid', [passport.authenticate(['basic', 'jwt'], { session:
|
|
|
79
80
|
if (req.body.status!=undefined) {
|
|
80
81
|
update.status = req.body.status;
|
|
81
82
|
}
|
|
82
|
-
|
|
83
|
+
if (req.body.groups!=undefined) {
|
|
84
|
+
update.groups = req.body.groups;
|
|
85
|
+
}
|
|
83
86
|
|
|
84
87
|
|
|
85
88
|
Department.findByIdAndUpdate(req.params.departmentid, update, { new: true, upsert: true }, function (err, updatedDepartment) {
|
|
@@ -121,6 +124,9 @@ router.put('/:departmentid', [passport.authenticate(['basic', 'jwt'], { session:
|
|
|
121
124
|
if (req.body.id_group!=undefined) {
|
|
122
125
|
update.id_group = req.body.id_group;
|
|
123
126
|
}
|
|
127
|
+
if (req.body.groups!=undefined) {
|
|
128
|
+
update.groups = req.body.groups;
|
|
129
|
+
}
|
|
124
130
|
|
|
125
131
|
|
|
126
132
|
Department.findByIdAndUpdate(req.params.departmentid, update, { new: true, upsert: true }, function (err, updatedDepartment) {
|