@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.
Files changed (49) hide show
  1. package/CHANGELOG.md +8 -3
  2. package/app.js +4 -0
  3. package/channels/chat21/chat21WebHook.js +6 -1
  4. package/docs/routes-answered.md +153 -0
  5. package/event/authEvent.js +16 -0
  6. package/event/projectUserEvent.js +39 -0
  7. package/event/roleEvent.js +9 -0
  8. package/middleware/has-role.js +160 -121
  9. package/middleware/passport.js +180 -179
  10. package/migrations/1757601159298-project_user_role_type.js +104 -0
  11. package/models/department.js +3 -0
  12. package/models/groupMemberSchama.js +19 -0
  13. package/models/kb_setting.js +74 -4
  14. package/models/permissionConstants.js +19 -0
  15. package/models/project_user.js +86 -8
  16. package/models/request.js +1 -0
  17. package/models/role.js +31 -0
  18. package/models/roleConstants.js +2 -0
  19. package/package.json +1 -1
  20. package/pubmodules/analytics/analytics.js +2 -2
  21. package/pubmodules/cache/mongoose-cachegoose-fn.js +37 -0
  22. package/pubmodules/canned/cannedResponseRoute.js +34 -6
  23. package/pubmodules/routing-queue/listener.js +7 -1
  24. package/pubmodules/trigger/rulesTrigger.js +1 -6
  25. package/routes/answered.js +227 -0
  26. package/routes/auth.js +3 -1
  27. package/routes/department.js +7 -1
  28. package/routes/message.js +4 -1
  29. package/routes/project.js +41 -3
  30. package/routes/project_user.js +62 -11
  31. package/routes/request.js +32 -30
  32. package/routes/roles.js +151 -0
  33. package/routes/unanswered.js +32 -19
  34. package/routes/widget.js +3 -1
  35. package/services/cacheEnabler.js +5 -8
  36. package/services/departmentService.js +39 -11
  37. package/services/emailService.js +2 -2
  38. package/services/pendingInvitationService.js +2 -0
  39. package/services/projectService.js +3 -1
  40. package/services/projectUserService.js +67 -4
  41. package/services/subscriptionNotifierQueued.js +8 -0
  42. package/services/updateRequestSnapshotQueued.js +0 -3
  43. package/test/departmentService.js +5 -0
  44. package/test/messageRoute.js +7 -4
  45. package/test/projectUserRoute.js +116 -0
  46. package/test/requestService.js +7 -3
  47. package/test-int/bot.js +3 -2
  48. package/websocket/webSocketServer.js +273 -225
  49. package/routes/auth_newjwt.js +0 -648
@@ -81,13 +81,20 @@ winston.info('Authentication Oauth2 Signin enabled : ' + enableOauth2Signin);
81
81
 
82
82
  var jwthistory = undefined;
83
83
  try {
84
- jwthistory = require('@tiledesk-ent/tiledesk-server-jwthistory');
85
- } catch (err) {
86
- winston.debug("jwthistory not present");
84
+ jwthistory = require('@tiledesk-ent/tiledesk-server-jwthistory');
85
+ } catch(err) {
86
+ winston.info("jwthistory not present", err);
87
87
  }
88
88
 
89
- module.exports = function (passport) {
89
+ let JWT_HISTORY_ENABLED = false;
90
+ if (process.env.JWT_HISTORY_ENABLED==true || process.env.JWT_HISTORY_ENABLED=="true") {
91
+ JWT_HISTORY_ENABLED = true;
92
+ }
93
+ winston.debug("JWT_HISTORY_ENABLED: " + JWT_HISTORY_ENABLED);
94
+
95
+
90
96
 
97
+ module.exports = function(passport) {
91
98
  // passport.serializeUser(function(user, done) {
92
99
  // console.log("serializeUser");
93
100
 
@@ -231,218 +238,212 @@ module.exports = function (passport) {
231
238
  done(null, configSecret); //pub_jwt pp_jwt
232
239
  }
233
240
  }
234
- }
241
+ };
235
242
 
236
243
 
237
- winston.debug("passport opts: ", opts);
244
+ winston.debug("passport opts: ", opts);
238
245
 
239
- passport.use(new JwtStrategy(opts, async (req, jwt_payload, done) => {
240
- // passport.use(new JwtStrategy(opts, function(req, jwt_payload, done) {
241
- winston.debug("jwt_payload", jwt_payload);
242
- // console.log("req",req);
246
+ passport.use(new JwtStrategy(opts, async(req, jwt_payload, done) => {
247
+ // passport.use(new JwtStrategy(opts, function(req, jwt_payload, done) {
248
+ winston.debug("jwt_payload",jwt_payload);
249
+ // console.log("req",req);
250
+
243
251
 
252
+ // console.log("jwt_payload._doc._id",jwt_payload._doc._id);
244
253
 
245
- // console.log("jwt_payload._doc._id",jwt_payload._doc._id);
246
254
 
255
+ if (jwt_payload._id == undefined && (jwt_payload._doc == undefined || (jwt_payload._doc && jwt_payload._doc._id==undefined))) {
256
+ var err = "jwt_payload._id or jwt_payload._doc._id can t be undefined" ;
257
+ winston.error(err);
258
+ return done(null, false);
259
+ }
260
+ //JWT OLD format
261
+ const identifier = jwt_payload._id || jwt_payload._doc._id;
262
+
263
+ // const subject = jwt_payload.sub || jwt_payload._id || jwt_payload._doc._id;
264
+ winston.debug("passport identifier: " + identifier);
247
265
 
248
- if (jwt_payload._id == undefined && (jwt_payload._doc == undefined || (jwt_payload._doc && jwt_payload._doc._id == undefined))) {
249
- var err = "jwt_payload._id or jwt_payload._doc._id can t be undefined";
250
- winston.error(err);
251
- return done(null, false);
252
- }
253
- //JWT OLD format
254
- const identifier = jwt_payload._id || jwt_payload._doc._id;
266
+ const subject = jwt_payload.sub;
267
+ winston.debug("passport subject: " + subject);
255
268
 
256
- // const subject = jwt_payload.sub || jwt_payload._id || jwt_payload._doc._id;
257
- winston.debug("passport identifier: " + identifier);
269
+ winston.debug("passport identifier: " + identifier + " subject " + subject);
258
270
 
259
- const subject = jwt_payload.sub;
260
- winston.debug("passport subject: " + subject);
271
+ var fullUrl = req.protocol + '://' + req.get('host') + req.originalUrl;
272
+ winston.debug("fullUrl:"+ fullUrl);
261
273
 
262
- winston.debug("passport identifier: " + identifier + " subject " + subject);
274
+ winston.debug("req.disablePassportEntityCheck:"+req.disablePassportEntityCheck);
263
275
 
264
- var fullUrl = req.protocol + '://' + req.get('host') + req.originalUrl;
265
- winston.debug("fullUrl:" + fullUrl);
276
+ if (req && req.disablePassportEntityCheck) { //req can be null
277
+ // jwt_payload.id = jwt_payload._id; //often req.user.id is used inside code. req.user.id is a mongoose getter of _id
278
+ // is better to rename req.user.id to req.user._id in all files
279
+ winston.debug("req.disablePassportEntityCheck enabled");
280
+ return done(null, jwt_payload);
281
+ }
282
+ winston.debug("jwthistory passport",jwthistory);
283
+
284
+ //TODO check into DB if JWT is revoked
285
+ if (jwthistory && JWT_HISTORY_ENABLED==true) {
286
+ var jwtRevoked = await jwthistory.isJWTRevoked(jwt_payload.jti);
287
+ winston.debug("passport jwt jwtRevoked: "+ jwtRevoked);
288
+ if (jwtRevoked) {
289
+ winston.warn("passport jwt is revoked with jti: "+ jwt_payload.jti);
290
+ return done(null, false);
291
+ }
292
+ }
266
293
 
267
- winston.debug("req.disablePassportEntityCheck:" + req.disablePassportEntityCheck);
294
+ if (subject == "bot") {
295
+ winston.debug("Passport JWT bot");
268
296
 
269
- if (req && req.disablePassportEntityCheck) { //req can be null
270
- // jwt_payload.id = jwt_payload._id; //often req.user.id is used inside code. req.user.id is a mongoose getter of _id
271
- // is better to rename req.user.id to req.user._id in all files
272
- winston.debug("req.disablePassportEntityCheck enabled");
273
- return done(null, jwt_payload);
274
- }
297
+ let qbot = Faq_kb.findOne({_id: identifier}); //TODO add cache_bot_here
275
298
 
276
- //TODO check into DB if JWT is revoked
277
- if (jwthistory) {
278
- var jwtRevoked = await jwthistory.isJWTRevoked(jwt_payload.jti);
279
- winston.debug("passport jwt jwtRevoked: " + jwtRevoked);
280
- if (jwtRevoked) {
281
- winston.warn("passport jwt is revoked with jti: " + jwt_payload.jti);
282
- return done(null, false);
283
- }
299
+ if (cacheEnabler.faq_kb) {
300
+ let id_project = jwt_payload.id_project;
301
+ winston.debug("jwt_payload.id_project:"+jwt_payload.id_project);
302
+ qbot.cache(cacheUtil.defaultTTL, id_project+":faq_kbs:id:"+identifier)
303
+ winston.debug('faq_kb cache enabled');
304
+ }
305
+
306
+ qbot.exec(function(err, faq_kb) {
307
+
308
+ if (err) {
309
+ winston.error("Passport JWT bot err", err);
310
+ return done(err, false);
311
+ }
312
+ if (faq_kb) {
313
+ winston.debug("Passport JWT bot user", faq_kb);
314
+ return done(null, faq_kb);
315
+ } else {
316
+ winston.warn("Passport JWT bot not user");
317
+ return done(null, false);
318
+ }
319
+ });
320
+ // } else if (subject=="projects") {
321
+
322
+ } else if (subject=="subscription") {
323
+
324
+ Subscription.findOne({_id: identifier}, function(err, subscription) {
325
+ if (err) {
326
+ winston.error("Passport JWT subscription err", err);
327
+ return done(err, false);
328
+ }
329
+ if (subscription) {
330
+ winston.debug("Passport JWT subscription user", subscription);
331
+ return done(null, subscription);
332
+ } else {
333
+ winston.warn("Passport JWT subscription not user", subscription);
334
+ return done(null, false);
284
335
  }
336
+ });
285
337
 
286
- if (subject == "bot") {
287
- winston.debug("Passport JWT bot");
338
+ } else if (subject=="userexternal") {
339
+
340
+
341
+ if (jwt_payload) {
288
342
 
289
- let qbot = Faq_kb.findOne({_id: identifier}); //TODO add cache_bot_here
343
+ // const audUrl = new URL(jwt_payload.aud);
344
+ // winston.info("audUrl: "+ audUrl );
290
345
 
291
- if (cacheEnabler.faq_kb) {
292
- let id_project = jwt_payload.id_project;
293
- winston.debug("jwt_payload.id_project:" + jwt_payload.id_project);
294
- qbot.cache(cacheUtil.defaultTTL, id_project + ":faq_kbs:id:" + identifier)
295
- winston.debug('faq_kb cache enabled');
296
- }
346
+ // const path = audUrl.pathname;
347
+ // winston.info("audUrl path: " + path );
348
+
349
+ // const AudienceType = path.split("/")[1];
350
+ // winston.info("audUrl AudienceType: " + AudienceType );
297
351
 
298
- qbot.exec(function (err, faq_kb) {
352
+ // const AudienceId = path.split("/")[2];
353
+ // winston.info("audUrl AudienceId: " + AudienceId );
299
354
 
300
- if (err) {
301
- winston.error("Passport JWT bot err", err);
302
- return done(err, false);
303
- }
304
- if (faq_kb) {
305
- winston.debug("Passport JWT bot user", faq_kb);
306
- return done(null, faq_kb);
307
- } else {
308
- winston.warn("Passport JWT bot not user");
309
- return done(null, false);
310
- }
311
- });
312
- // } else if (subject=="projects") {
355
+ // jwt_payload._id = AudienceId + "-" + jwt_payload._id;
356
+
313
357
 
314
- } else if (subject == "subscription") {
315
358
 
316
- Subscription.findOne({_id: identifier}, function (err, subscription) {
317
- if (err) {
318
- winston.error("Passport JWT subscription err", err);
319
- return done(err, false);
320
- }
321
- if (subscription) {
322
- winston.debug("Passport JWT subscription user", subscription);
323
- return done(null, subscription);
324
- } else {
325
- winston.warn("Passport JWT subscription not user", subscription);
326
- return done(null, false);
327
- }
328
- });
359
+ winston.debug("Passport JWT userexternal", jwt_payload);
360
+ var userM = UserUtil.decorateUser(jwt_payload);
361
+ winston.debug("Passport JWT userexternal userM", userM);
329
362
 
330
- } else if (subject == "userexternal") {
363
+ return done(null, userM );
364
+ } else {
365
+ var err = {msg: "No jwt_payload passed. Its required"};
366
+ winston.error("Passport JWT userexternal err", err);
367
+ return done(err, false);
368
+ }
331
369
 
370
+ } else if (subject=="guest") {
371
+
372
+
373
+ if (jwt_payload) {
374
+ winston.debug("Passport JWT guest", jwt_payload);
375
+ var userM = UserUtil.decorateUser(jwt_payload);
376
+ winston.debug("Passport JWT guest userM", userM);
377
+ return done(null, userM );
378
+ } else {
379
+ var err = {msg: "No jwt_payload passed. Its required"};
380
+ winston.error("Passport JWT guest err", err);
381
+ return done(err, false);
382
+ }
383
+
384
+ } else {
385
+ winston.debug("Passport JWT generic user");
386
+ let quser = User.findOne({_id: identifier, status: 100}) //TODO user_cache_here
387
+ //@DISABLED_CACHE .cache(cacheUtil.defaultTTL, "users:id:"+identifier)
388
+
389
+ if (cacheEnabler.user) {
390
+ quser.cache(cacheUtil.defaultTTL, "users:id:"+identifier)
391
+ winston.debug('user cache enabled');
392
+ }
332
393
 
333
- if (jwt_payload) {
394
+ quser.exec(function(err, user) {
395
+ if (err) {
396
+ winston.error("Passport JWT generic err ", err);
397
+ return done(err, false);
398
+ }
399
+ if (user) {
400
+ winston.debug("Passport JWT generic user ", user);
401
+ return done(null, user);
402
+ } else {
403
+ winston.debug("Passport JWT generic not user");
404
+ return done(null, false);
405
+ }
406
+ });
334
407
 
335
- // const audUrl = new URL(jwt_payload.aud);
336
- // winston.info("audUrl: "+ audUrl );
408
+ }
409
+
337
410
 
338
- // const path = audUrl.pathname;
339
- // winston.info("audUrl path: " + path );
340
411
 
341
- // const AudienceType = path.split("/")[1];
342
- // winston.info("audUrl AudienceType: " + AudienceType );
412
+ }));
343
413
 
344
- // const AudienceId = path.split("/")[2];
345
- // winston.info("audUrl AudienceId: " + AudienceId );
346
414
 
347
- // jwt_payload._id = AudienceId + "-" + jwt_payload._id;
348
415
 
416
+ passport.use(new BasicStrategy(function(userid, password, done) {
417
+
418
+ winston.debug("BasicStrategy: " + userid);
419
+
349
420
 
350
- winston.debug("Passport JWT userexternal", jwt_payload);
351
- var userM = UserUtil.decorateUser(jwt_payload);
352
- winston.debug("Passport JWT userexternal userM", userM);
421
+ var email = userid.toLowerCase();
422
+ winston.debug("email lowercase: " + email);
353
423
 
354
- return done(null, userM);
355
- } else {
356
- var err = {msg: "No jwt_payload passed. Its required"};
357
- winston.error("Passport JWT userexternal err", err);
358
- return done(err, false);
359
- }
360
-
361
- } else if (subject == "guest") {
424
+ User.findOne({ email: email, status: 100}, 'email firstname lastname password emailverified id') //TODO user_cache_here. NOT used frequently. ma attento select. ATTENTO QUI NN USEREI LA SELECT altrimenti con JWT ho tuttto USER mentre con basich auth solo aluni campi
425
+ //@DISABLED_CACHE .cache(cacheUtil.defaultTTL, "users:email:"+email)
426
+ .exec(function (err, user) {
427
+
428
+ if (err) {
429
+ // console.log("BasicStrategy err.stop");
430
+ return done(err);
431
+ }
432
+ if (!user) { return done(null, false); }
433
+
434
+ user.comparePassword(password, function (err, isMatch) {
435
+ if (isMatch && !err) {
362
436
 
437
+ // if user is found and password is right create a token
438
+ // console.log("BasicStrategy ok");
439
+ return done(null, user);
363
440
 
364
- if (jwt_payload) {
365
- winston.debug("Passport JWT guest", jwt_payload);
366
- var userM = UserUtil.decorateUser(jwt_payload);
367
- winston.debug("Passport JWT guest userM", userM);
368
- return done(null, userM);
369
441
  } else {
370
- var err = {msg: "No jwt_payload passed. Its required"};
371
- winston.error("Passport JWT guest err", err);
372
- return done(err, false);
442
+ return done(err);
373
443
  }
374
-
375
- } else {
376
- winston.debug("Passport JWT generic user");
377
- let quser = User.findOne({_id: identifier, status: 100}) //TODO user_cache_here
378
- //@DISABLED_CACHE .cache(cacheUtil.defaultTTL, "users:id:"+identifier)
379
-
380
- if (cacheEnabler.user) {
381
- quser.cache(cacheUtil.defaultTTL, "users:id:" + identifier)
382
- winston.debug('user cache enabled');
383
- }
384
-
385
- quser.exec(function (err, user) {
386
- if (err) {
387
- winston.error("Passport JWT generic err ", err);
388
- return done(err, false);
389
- }
390
- if (user) {
391
- winston.debug("Passport JWT generic user ", user);
392
- return done(null, user);
393
- } else {
394
- winston.debug("Passport JWT generic not user");
395
- return done(null, false);
396
- }
397
- });
398
-
399
- }
400
-
401
-
402
- }));
403
-
404
-
405
- passport.use(new BasicStrategy(function (userid, password, done) {
406
-
407
- winston.debug("BasicStrategy: " + userid);
408
-
409
-
410
- var email = userid.toLowerCase();
411
- winston.debug("email lowercase: " + email);
412
-
413
- User.findOne({
414
- email: email,
415
- status: 100
416
- }, 'email firstname lastname password emailverified id') //TODO user_cache_here. NOT used frequently. ma attento select. ATTENTO QUI NN USEREI LA SELECT altrimenti con JWT ho tuttto USER mentre con basich auth solo aluni campi
417
- //@DISABLED_CACHE .cache(cacheUtil.defaultTTL, "users:email:"+email)
418
- .exec(function (err, user) {
419
-
420
- if (err) {
421
- // console.log("BasicStrategy err.stop");
422
- return done(err);
423
- }
424
- if (!user) {
425
- return done(null, false);
426
- }
427
-
428
- user.comparePassword(password, function (err, isMatch) {
429
- if (isMatch && !err) {
430
-
431
- // if user is found and password is right create a token
432
- // console.log("BasicStrategy ok");
433
- return done(null, user);
434
-
435
- } else {
436
- return done(err);
437
- }
438
- });
439
-
440
-
441
- // if (user) { return done(null, user); }
442
- // if (!user) { return done(null, false); }
443
- // if (!user.verifyPassword(password)) { return done(null, false); }
444
- });
445
- }));
444
+ });
445
+ });
446
+ }));
446
447
 
447
448
 
448
449
  if (enableGoogleSignin == true) {
@@ -0,0 +1,104 @@
1
+ var Project_user = require("../models/project_user");
2
+ var winston = require('../config/winston');
3
+
4
+ const BATCH_SIZE = 100;
5
+ /** Log a progress line every this many bulkWrite rounds (plus always after the 1st). */
6
+ const PROGRESS_LOG_EVERY_BATCHES = 10;
7
+
8
+ /** Only documents that still need roleType (idempotent re-runs). */
9
+ const WITHOUT_ROLE_TYPE = {
10
+ $or: [{ roleType: { $exists: false } }, { roleType: null }]
11
+ };
12
+
13
+ const AGENT_ROLES_FILTER = {
14
+ $and: [
15
+ {
16
+ $or: [
17
+ { role: 'agent' },
18
+ { role: 'supervisor' },
19
+ { role: 'admin' },
20
+ { role: 'owner' }
21
+ ]
22
+ },
23
+ WITHOUT_ROLE_TYPE
24
+ ]
25
+ };
26
+
27
+ const USER_ROLES_FILTER = {
28
+ $and: [{ $or: [{ role: 'user' }, { role: 'guest' }] }, WITHOUT_ROLE_TYPE]
29
+ };
30
+
31
+ async function batchSetRoleType(filter, roleType, phaseLabel) {
32
+ const totalMatching = await Project_user.countDocuments(filter);
33
+ const started = Date.now();
34
+ winston.info(
35
+ `[project_user_role_type] ${phaseLabel}: ${totalMatching} documents match filter; streaming _id + bulkWrite in chunks of ${BATCH_SIZE}`
36
+ );
37
+
38
+ let modified = 0;
39
+ let scanned = 0;
40
+ let bulkRounds = 0;
41
+ const cursor = Project_user.find(filter).select('_id').lean().cursor();
42
+ let batch = [];
43
+
44
+ function logProgress(reason) {
45
+ const elapsedSec = ((Date.now() - started) / 1000).toFixed(1);
46
+ winston.info(
47
+ `[project_user_role_type] ${phaseLabel} ${reason}: scanned=${scanned}/${totalMatching}, modifiedThisPhase=${modified}, ${elapsedSec}s elapsed`
48
+ );
49
+ }
50
+
51
+ for await (const doc of cursor) {
52
+ scanned++;
53
+ batch.push({
54
+ updateOne: {
55
+ filter: { _id: doc._id, ...WITHOUT_ROLE_TYPE },
56
+ update: { $set: { roleType } }
57
+ }
58
+ });
59
+ if (batch.length >= BATCH_SIZE) {
60
+ const result = await Project_user.bulkWrite(batch);
61
+ modified += result.modifiedCount;
62
+ batch = [];
63
+ bulkRounds++;
64
+ if (bulkRounds === 1 || bulkRounds % PROGRESS_LOG_EVERY_BATCHES === 0) {
65
+ logProgress(`progress (bulk round ${bulkRounds})`);
66
+ }
67
+ }
68
+ }
69
+ if (batch.length > 0) {
70
+ const result = await Project_user.bulkWrite(batch);
71
+ modified += result.modifiedCount;
72
+ bulkRounds++;
73
+ logProgress(`final partial batch (bulk round ${bulkRounds})`);
74
+ }
75
+
76
+ logProgress('phase complete');
77
+ return modified;
78
+ }
79
+
80
+ /**
81
+ * Make any changes you need to make to the database here
82
+ */
83
+ async function up() {
84
+ try {
85
+ const agentsModified = await batchSetRoleType(AGENT_ROLES_FILTER, 1, 'agents roleType=1');
86
+ winston.info(`[project_user_role_type] Agents phase done: ${agentsModified} documents modified`);
87
+
88
+ const usersModified = await batchSetRoleType(USER_ROLES_FILTER, 2, 'users/guest roleType=2');
89
+ winston.info(`[project_user_role_type] Users/guest phase done: ${usersModified} documents modified`);
90
+ } catch (err) {
91
+ winston.error('[project_user_role_type] Error applying migration:', err);
92
+ throw err;
93
+ }
94
+ }
95
+
96
+ /**
97
+ * Make any changes that UNDO the up function side effects here (if possible)
98
+ */
99
+ async function down() {
100
+ // Write migration here
101
+ // console.log("down*********");
102
+ }
103
+
104
+ module.exports = { up, down };
@@ -3,6 +3,8 @@ var Schema = mongoose.Schema;
3
3
  var routingConstants = require('../models/routingConstants');
4
4
  var winston = require('../config/winston');
5
5
  var TagSchema = require("../models/tag");
6
+ var GroupMemberSchema = require("../models/groupMemberSchama");
7
+
6
8
 
7
9
  var DepartmentSchema = new Schema({
8
10
  id_bot: {
@@ -34,6 +36,7 @@ var DepartmentSchema = new Schema({
34
36
  id_group: {
35
37
  type: String,
36
38
  },
39
+ groups: [GroupMemberSchema],
37
40
  // used??
38
41
  online_msg: {
39
42
  type: String,
@@ -0,0 +1,19 @@
1
+ var mongoose = require('mongoose');
2
+ var Schema = mongoose.Schema;
3
+ var winston = require('../config/winston');
4
+
5
+ var GroupMemberSchema = new Schema({
6
+
7
+ group_id: {
8
+ type: String,
9
+ required: true
10
+ },
11
+ percentage: {
12
+ type: Number,
13
+ required: true,
14
+ }
15
+ }
16
+ );
17
+
18
+
19
+ module.exports = GroupMemberSchema;
@@ -1,7 +1,25 @@
1
1
  let mongoose = require('mongoose');
2
2
  let Schema = mongoose.Schema;
3
3
  let winston = require('../config/winston');
4
- let expireAfterSeconds = process.env.UNANSWERED_QUESTION_EXPIRATION_TIME || 7 * 24 * 60 * 60; // 7 days
4
+
5
+ const DEFAULT_UNANSWERED_TTL_SEC = 7 * 24 * 60 * 60; // 7 days
6
+ const DEFAULT_ANSWERED_TTL_SEC = 7 * 24 * 60 * 60; // 7 days
7
+
8
+ function ttlSecondsFromEnv(raw, fallbackSec) {
9
+ if (raw == null || String(raw).trim() === '') return fallbackSec;
10
+ const n = Number(raw);
11
+ return Number.isFinite(n) && n >= 0 ? n : fallbackSec;
12
+ }
13
+
14
+ let expireAfterSeconds = ttlSecondsFromEnv(
15
+ process.env.UNANSWERED_QUESTION_EXPIRATION_TIME,
16
+ DEFAULT_UNANSWERED_TTL_SEC
17
+ );
18
+ let expireAnsweredAfterSeconds = ttlSecondsFromEnv(
19
+ process.env.ANSWERED_QUESTION_EXPIRATION_TIME,
20
+ DEFAULT_ANSWERED_TTL_SEC
21
+ );
22
+
5
23
 
6
24
  const EngineSchema = new Schema({
7
25
  name: {
@@ -199,13 +217,63 @@ const UnansweredQuestionSchema = new Schema({
199
217
  question: {
200
218
  type: String,
201
219
  required: true
220
+ },
221
+ request_id: {
222
+ type: String,
223
+ required: false,
224
+ },
225
+ sender: {
226
+ type: String,
227
+ required: false,
202
228
  }
203
229
  },{
204
230
  timestamps: true
205
231
  });
206
232
 
207
- // Add TTL index to automatically delete documents after 30 days
208
- UnansweredQuestionSchema.index({ created_at: 1 }, { expireAfterSeconds: expireAfterSeconds }); // 30 days
233
+ const AnsweredQuestionSchema = new Schema({
234
+ id_project: {
235
+ type: String,
236
+ required: true,
237
+ index: true
238
+ },
239
+ namespace: {
240
+ type: String,
241
+ required: true,
242
+ index: true
243
+ },
244
+ question: {
245
+ type: String,
246
+ required: true
247
+ },
248
+ answer: {
249
+ type: String,
250
+ required: true
251
+ },
252
+ tokens: {
253
+ type: Number,
254
+ required: false
255
+ },
256
+ request_id: {
257
+ type: String,
258
+ required: false
259
+ }
260
+ }, {
261
+ timestamps: true
262
+ });
263
+
264
+ // Add TTL index to automatically delete documents
265
+ UnansweredQuestionSchema.index({ createdAt: 1 }, { expireAfterSeconds: expireAfterSeconds });
266
+ UnansweredQuestionSchema.index({ id_project: 1, namespace: 1, createdAt: -1 });
267
+ UnansweredQuestionSchema.index({ question: "text" });
268
+
269
+ AnsweredQuestionSchema.index({ createdAt: 1 }, { expireAfterSeconds: expireAnsweredAfterSeconds });
270
+ AnsweredQuestionSchema.index({ id_project: 1, namespace: 1, createdAt: -1 });
271
+ AnsweredQuestionSchema.index(
272
+ { question: "text", answer: "text" },
273
+ { weights: { question: 3, answer: 1 } }
274
+ );
275
+
276
+
209
277
 
210
278
  // DEPRECATED !! - Start
211
279
  const KBSettingSchema = new Schema({
@@ -242,6 +310,7 @@ const Engine = mongoose.model('Engine', EngineSchema)
242
310
  const Namespace = mongoose.model('Namespace', NamespaceSchema)
243
311
  const KB = mongoose.model('KB', KBSchema)
244
312
  const UnansweredQuestion = mongoose.model('UnansweredQuestion', UnansweredQuestionSchema)
313
+ const AnsweredQuestion = mongoose.model('AnsweredQuestion', AnsweredQuestionSchema)
245
314
 
246
315
 
247
316
  module.exports = {
@@ -249,5 +318,6 @@ module.exports = {
249
318
  Namespace: Namespace,
250
319
  Engine: Engine,
251
320
  KB: KB,
252
- UnansweredQuestion: UnansweredQuestion
321
+ UnansweredQuestion: UnansweredQuestion,
322
+ AnsweredQuestion: AnsweredQuestion
253
323
  }
@@ -0,0 +1,19 @@
1
+ const OWNER_ROLE = [
2
+ ];
3
+
4
+ const ADMIN_ROLE = [
5
+ "request_read_all"
6
+ ];
7
+ const AGENT_ROLE= [
8
+ "request_read_group"
9
+ ];
10
+
11
+ // console.log("ADMIN_ROLE", ADMIN_ROLE.concat(AGENT_ROLE));
12
+ module.exports = {
13
+ "agent": AGENT_ROLE,
14
+ "admin": ADMIN_ROLE.concat(AGENT_ROLE),
15
+ "owner": OWNER_ROLE.concat(ADMIN_ROLE).concat(AGENT_ROLE)
16
+
17
+ }
18
+ // const ADMIN_ROLE = Object.assign({}, ADMIN_ROLE, AGENT_ROLE)
19
+ // const ADMIN_ROLE = { ...ADMIN_ROLE, ...AGENT_ROLE }