@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
package/CHANGELOG.md CHANGED
@@ -5,11 +5,16 @@
5
5
  🚀 IN PRODUCTION 🚀
6
6
  (https://www.npmjs.com/package/@tiledesk/tiledesk-server/v/2.3.77)
7
7
 
8
- # 2.17.5
9
- - Refactor error handling and code structure in webhook.js
8
+ # 2.18.3
9
+ - Added permissions logic
10
+ - Added custom roles support
11
+ - Add answered questions functionality
12
+ - Added AnsweredQuestion schema with TTL index for automatic deletion.
13
+ - Updated UnansweredQuestion schema to include additional fields and improved query handling for searching and sorting.
14
+ - Enhanced the deletion process for unanswered questions.
10
15
 
11
16
  # 2.17.4
12
- - Added support for Pinecone Reranking for Standard knowledge bases
17
+ - Refactor error handling and code structure in webhook.js
13
18
 
14
19
  # 2.17.3
15
20
  - Added missing import path on kb route
package/app.js CHANGED
@@ -130,6 +130,7 @@ var integration = require('./routes/integration')
130
130
  var kbsettings = require('./routes/kbsettings');
131
131
  var kb = require('./routes/kb');
132
132
  var unanswered = require('./routes/unanswered');
133
+ var answered = require('./routes/answered');
133
134
 
134
135
  // var admin = require('./routes/admin');
135
136
  var faqpub = require('./routes/faqpub');
@@ -149,6 +150,7 @@ var property = require('./routes/property');
149
150
  var segment = require('./routes/segment');
150
151
  var webhook = require('./routes/webhook');
151
152
  var webhooks = require('./routes/webhooks');
153
+ var roles = require('./routes/roles');
152
154
  var copilot = require('./routes/copilot');
153
155
  var mcp = require('./routes/mcp');
154
156
 
@@ -642,12 +644,14 @@ app.use('/:projectid/mcp', [passport.authenticate(['basic', 'jwt'], { session: f
642
644
 
643
645
  app.use('/:projectid/kbsettings', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('agent', ['bot','subscription'])], kbsettings);
644
646
  app.use('/:projectid/kb/unanswered', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('admin', ['bot','subscription'])], unanswered);
647
+ app.use('/:projectid/kb/answered', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('admin', ['bot','subscription'])], answered);
645
648
  app.use('/:projectid/kb', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('admin', ['bot','subscription'])], kb);
646
649
 
647
650
  app.use('/:projectid/logs', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRole('agent')], logs);
648
651
 
649
652
  app.use('/:projectid/webhooks', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRole('admin')], webhooks);
650
653
  app.use('/:projectid/copilot', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRole('agent')], copilot);
654
+ app.use('/:projectid/roles', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRole('agent')], roles);
651
655
 
652
656
  app.use('/:projectid/files', filesp);
653
657
 
@@ -307,7 +307,12 @@ router.post('/', function (req, res) {
307
307
  // TODO se stato = 50 e scrive visitatotre sposto a stato 100 poi queuue lo smista
308
308
 
309
309
  // TOOD update also request attributes and sourcePage
310
-
310
+ if (message.sender !== 'system') {
311
+ Request.findOneAndUpdate({request_id: request.request_id, id_project: request.id_project}, { "attributes.last_message": savedMessage}).catch((err) => {
312
+ winston.error("Create message - saving last message in request error: ", err);
313
+ })
314
+ }
315
+
311
316
  // return requestService.incrementMessagesCountByRequestId(request.request_id, request.id_project).then(function(savedRequest) {
312
317
  // winston.debug("savedRequest.participants.indexOf(message.sender)", savedRequest.participants.indexOf(message.sender));
313
318
  winston.debug("before updateWaitingTimeByRequestId*******",request.participants, message.sender);
@@ -0,0 +1,153 @@
1
+ # Route `kb/answered` — domande con risposta (Knowledge Base)
2
+
3
+ Documentazione per [`routes/answered.js`](../routes/answered.js).
4
+
5
+ ## Scopo
6
+
7
+ API REST per gestire le **domande già risposte** associate a un **namespace** della Knowledge Base del progetto. I documenti sono persistiti nel modello Mongoose `AnsweredQuestion` (vedi [`models/kb_setting.js`](../models/kb_setting.js)).
8
+
9
+ Ogni operazione è vincolata al **progetto corrente** (`req.projectid`, derivato dal segmento `:projectid` nell’URL) e alla validità del **namespace** (deve esistere un `Namespace` con `id` uguale al `namespace` richiesto e `id_project` uguale al progetto).
10
+
11
+ ## Montaggio e autenticazione
12
+
13
+ In [`app.js`](../app.js) il router è montato così:
14
+
15
+ - **Path base:** `/:projectid/kb/answered`
16
+ - **Middleware:** `passport.authenticate(['basic', 'jwt'])`, `validtoken`, `roleChecker.hasRoleOrTypes('admin', ['bot','subscription'])`
17
+
18
+ Sono quindi richiesti autenticazione (Basic o JWT), token valido e ruolo **admin** oppure tipi **bot** / **subscription**.
19
+
20
+ Esempio di URL completo (sviluppo locale):
21
+
22
+ ```http
23
+ GET http://localhost:3000/{projectId}/kb/answered/{namespace}
24
+ ```
25
+
26
+ Sostituire `{projectId}` con l’ID MongoDB del progetto.
27
+
28
+ ## Modello dati (`AnsweredQuestion`)
29
+
30
+ | Campo | Tipo | Note |
31
+ |---------------|----------|-------------------------------------------|
32
+ | `id_project` | string | Impostato dal server dal contesto progetto |
33
+ | `namespace` | string | ID del namespace (validato contro `Namespace`) |
34
+ | `question` | string | Obbligatorio |
35
+ | `answer` | string | Obbligatorio |
36
+ | `tokens` | number | Opzionale |
37
+ | `request_id` | string | Opzionale |
38
+ | `created_at` / `updated_at` | date | Da `timestamps: true` |
39
+
40
+ Indici rilevanti: TTL su `created_at`, indice composto `(id_project, namespace, created_at)`, indice **testo** su `question` e `answer` (pesi question 5, answer 1) per la ricerca full-text.
41
+
42
+ ---
43
+
44
+ ## Endpoint
45
+
46
+ Tutti i path qui sotto sono relativi a `/:projectid/kb/answered`.
47
+
48
+ ### `POST /`
49
+
50
+ Aggiunge una nuova domanda risposta.
51
+
52
+ **Body JSON**
53
+
54
+ | Campo | Obbligatorio | Descrizione |
55
+ |-------------|--------------|--------------------|
56
+ | `namespace` | sì | ID namespace |
57
+ | `question` | sì | Testo domanda |
58
+ | `answer` | sì | Testo risposta |
59
+ | `tokens` | no | Numero opzionale |
60
+ | `request_id`| no | Riferimento richiesta |
61
+
62
+ **Risposte**
63
+
64
+ | HTTP | Significato |
65
+ |------|-------------|
66
+ | 200 | Documento salvato (corpo = documento MongoDB creato) |
67
+ | 400 | Parametri mancanti (`namespace`, `question`, `answer`) |
68
+ | 403 | Namespace non appartenente al progetto |
69
+ | 500 | Errore server |
70
+
71
+ ---
72
+
73
+ ### `GET /:namespace`
74
+
75
+ Elenco paginato delle domande risposte per il namespace.
76
+
77
+ **Query**
78
+
79
+ | Parametro | Default | Descrizione |
80
+ |--------------|---------|-------------|
81
+ | `page` | `0` | Pagina (0-based) |
82
+ | `limit` | `20` | Elementi per pagina |
83
+ | `sortField` | `created_at` | Campo ordinamento |
84
+ | `direction` | `-1` | `1` crescente, `-1` decrescente |
85
+ | `search` | — | Se presente, attiva ricerca **full-text** (`$text`); l’ordinamento usa lo score di testo |
86
+
87
+ **Risposta 200**
88
+
89
+ ```json
90
+ {
91
+ "count": 0,
92
+ "questions": [],
93
+ "query": {
94
+ "page": 0,
95
+ "limit": 20,
96
+ "sortField": "created_at",
97
+ "direction": -1,
98
+ "search": "..."
99
+ }
100
+ }
101
+ ```
102
+
103
+ **Altri codici:** `400` (namespace mancante), `403` (namespace non valido per il progetto), `500`.
104
+
105
+ ---
106
+
107
+ ### `DELETE /:id`
108
+
109
+ Elimina una singola domanda per `_id` MongoDB.
110
+
111
+ **Risposte:** `200` con `{ success, message }`, `404` se non trovata (o non del progetto), `500`.
112
+
113
+ ---
114
+
115
+ ### `DELETE /namespace/:namespace`
116
+
117
+ Elimina **tutte** le domande risposte per `namespace` nel progetto corrente.
118
+
119
+ **Risposta 200:** `{ success, count: <deletedCount>, message }`.
120
+
121
+ **403** se il namespace non appartiene al progetto. **500** in errore.
122
+
123
+ ---
124
+
125
+ ### `GET /count/:namespace`
126
+
127
+ Restituisce il conteggio documenti per `id_project` + `namespace`.
128
+
129
+ **Risposta 200:** `{ count: <number> }`.
130
+
131
+ **400** / **403** / **500** come negli altri endpoint con validazione namespace.
132
+
133
+ ---
134
+
135
+ ## Funzione interna `validateNamespace(id_project, namespace_id)`
136
+
137
+ Verifica che esista un documento `Namespace` con `id_project` e `id: namespace_id`. Usata in creazione, lettura elenco, cancellazione bulk e conteggio.
138
+
139
+ ---
140
+
141
+ ## Nota sull’ordine delle route Express
142
+
143
+ Nel file è definito `GET /:namespace` **prima** di `GET /count/:namespace`. In Express la prima route che corrisponde vince: una richiesta del tipo `GET .../kb/answered/count/<namespace>` può essere interpretata come `GET /:namespace` con `namespace` uguale alla stringa letterale `count`, invece che come endpoint di conteggio.
144
+
145
+ Per far funzionare l’URL `GET /count/:namespace` come previsto dal codice, in genere occorre registrare **`GET /count/:namespace` prima di `GET /:namespace`**, oppure usare un prefisso path diverso per uno dei due. Verificare il comportamento in ambiente reale o adeguare l’ordine delle route se il conteggio non risponde come atteso.
146
+
147
+ ---
148
+
149
+ ## Riferimenti
150
+
151
+ - Router: [`routes/answered.js`](../routes/answered.js)
152
+ - Modello e indici: [`models/kb_setting.js`](../models/kb_setting.js) (`AnsweredQuestionSchema`)
153
+ - Montaggio app: [`app.js`](../app.js) (`/:projectid/kb/answered`)
@@ -1,4 +1,5 @@
1
1
  const EventEmitter = require('events');
2
+ var RoleConstants = require("../models/roleConstants");
2
3
 
3
4
  class AuthEvent extends EventEmitter {
4
5
  constructor() {
@@ -9,6 +10,21 @@ class AuthEvent extends EventEmitter {
9
10
 
10
11
  const authEvent = new AuthEvent();
11
12
 
13
+ var projectuserUpdateKey = 'project_user.update';
14
+ if (process.env.QUEUE_ENABLED === "true") {
15
+ projectuserUpdateKey = 'project_user.update.queue';
16
+ }
17
+
18
+ authEvent.on(projectuserUpdateKey, function(event) {
19
+ if (event.updatedProject_userPopulated) {
20
+ var pu = event.updatedProject_userPopulated;
21
+ if (pu.roleType === RoleConstants.TYPE_AGENTS) {
22
+ authEvent.emit("project_user.update.agent", event);
23
+ } else {
24
+ authEvent.emit("project_user.update.user", event);
25
+ }
26
+ }
27
+ });
12
28
 
13
29
  //listen for sigin and signup event
14
30
 
@@ -0,0 +1,39 @@
1
+ const EventEmitter = require('events');
2
+ const winston = require('../config/winston');
3
+ const Group = require("../models/group");
4
+
5
+ class ProjectUserEvent extends EventEmitter {
6
+ constructor() {
7
+ super();
8
+ this.registerListeners();
9
+ }
10
+
11
+ registerListeners() {
12
+
13
+ this.on('project_user.deleted', async (pu) => {
14
+
15
+ try {
16
+ winston.debug('[project_user.deleted] Event catched:', pu);
17
+
18
+ const id_project = pu.id_project;
19
+ let id_user = pu.id_user.toString();
20
+ if (typeof id_user === 'object' && id_user._id) {
21
+ id_user = id_user._id.toString();
22
+ }
23
+
24
+ const result = await Group.updateMany({ id_project: id_project }, { $pull: { members: id_user }});
25
+ winston.verbose(`Event project_user.deleted: User ${id_user} removed from ${result?.nModified} groups.`)
26
+
27
+ } catch (err) {
28
+ winston.verbose(`Event project_user.deleted: Error removing user ${id_user} from groups: `, err);
29
+ }
30
+
31
+ });
32
+
33
+ }
34
+ }
35
+
36
+ // Istanza singleton
37
+ const puEvent = new ProjectUserEvent();
38
+
39
+ module.exports = puEvent;
@@ -0,0 +1,9 @@
1
+ const EventEmitter = require('events');
2
+
3
+ class RoleEvent extends EventEmitter {}
4
+
5
+ const roleEvent = new RoleEvent();
6
+
7
+
8
+
9
+ module.exports = roleEvent;
@@ -1,18 +1,16 @@
1
- var Project_user = require("../models/project_user");
2
1
  var Faq_kb = require("../models/faq_kb");
3
2
  var Subscription = require("../models/subscription");
4
3
  var winston = require('../config/winston');
5
4
 
6
- var cacheUtil = require('../utils/cacheUtil');
7
- var cacheEnabler = require("../services/cacheEnabler");
8
-
5
+ var projectUserService = require("../services/projectUserService");
9
6
  class RoleChecker {
10
7
 
11
8
 
12
9
 
13
10
  constructor() {
11
+ winston.debug("RoleChecker");
14
12
 
15
- this.ROLES = {
13
+ this.ROLES = {
16
14
  "guest": ["guest"],
17
15
  "user": ["guest","user"],
18
16
  "teammate": ["guest","user","teammate"],
@@ -20,7 +18,7 @@ class RoleChecker {
20
18
  "supervisor": ["guest","user","teammate","agent","supervisor"],
21
19
  "admin": ["guest","user","teammate","agent", "supervisor", "admin"],
22
20
  "owner": ["guest","user","teammate","agent", "supervisor", "admin", "owner"],
23
- }
21
+ }
24
22
  }
25
23
 
26
24
  isType(type) {
@@ -87,18 +85,90 @@ class RoleChecker {
87
85
  }
88
86
 
89
87
 
88
+ hasPermission(permission) {
89
+ var that = this;
90
+ return async(req, res, next) => {
91
+ if (!req.params.projectid && !req.projectid) {
92
+ return res.status(400).send({success: false, msg: 'req.params.projectid is not defined.'});
93
+ }
94
+
95
+ let projectid = req.params.projectid || req.projectid;
96
+
97
+ var project_user = req.projectuser;
98
+ winston.debug("hasPermission project_user hasPermission", project_user);
99
+
100
+ if (!project_user) {
101
+
102
+ try {
103
+ project_user = await projectUserService.getWithPermissions(req.user._id, projectid, req.user.sub);
104
+ } catch(err) {
105
+ winston.error("Error getting project_user for hasrole",err);
106
+ return next(err);
107
+ }
108
+ winston.debug("project_user: ", JSON.stringify(project_user));
109
+ }
110
+
111
+ if (project_user) {
112
+
113
+ req.projectuser = project_user;
114
+ winston.debug("hasPermission req.projectuser", req.projectuser);
115
+
116
+ var permissions = project_user._doc.rolePermissions;
117
+
118
+ winston.debug("hasPermission permissions", permissions);
119
+
120
+ winston.debug("hasPermission permission: "+ permission);
121
+
122
+ if (permission==undefined) {
123
+ winston.debug("permission is empty go next");
124
+ return next();
125
+ }
126
+
127
+ if (permissions!=undefined && permissions.length>0) {
128
+ if (permissions.includes(permission)) {
129
+ next();
130
+ }else {
131
+ res.status(403).send({success: false, msg: 'you dont have the required permission.'});
132
+ }
133
+ } else {
134
+ res.status(403).send({success: false, msg: 'you dont have the required permission. Is is empty'});
135
+ }
136
+ } else {
137
+
138
+ /**
139
+ * Updated by Johnny - 29mar2024 - START
140
+ */
141
+ // console.log("req.user: ", req.user);
142
+ if (req.user.email === process.env.ADMIN_EMAIL) {
143
+ req.user.attributes = { isSuperadmin: true };
144
+ next();
145
+ } else {
146
+ res.status(403).send({success: false, msg: 'you dont belong to the project.'});
147
+ }
148
+ /**
149
+ * Updated by Johnny - 29mar2024 - END
150
+ */
151
+
152
+ }
153
+
154
+
155
+
156
+
157
+ }
158
+ }
90
159
 
91
160
 
92
161
  hasRole(role) {
93
162
  return this.hasRoleOrTypes(role);
94
163
  }
95
164
 
96
- hasRoleOrTypes(role, types) {
97
-
165
+ hasRoleOrTypes(role, types, permission) {
166
+ // console.log("hasRoleOrTypes",role,types);
167
+
98
168
  var that = this;
99
169
 
100
170
  // winston.debug("HasRole");
101
- return function(req, res, next) {
171
+ return async(req, res, next) => {
102
172
 
103
173
  // winston.debug("req.originalUrl" + req.originalUrl);
104
174
  // winston.debug("req.params" + JSON.stringify(req.params));
@@ -111,7 +181,7 @@ class RoleChecker {
111
181
 
112
182
  let projectid = req.params.projectid || req.projectid;
113
183
 
114
- // winston.info("req.user._id: " + req.user._id);
184
+ // winston.info("req.user._id: " + req.user._id);
115
185
 
116
186
  // winston.info("req.projectuser: " + req.projectuser);
117
187
  //winston.debug("req.user", req.user);
@@ -135,138 +205,107 @@ class RoleChecker {
135
205
  // res.status(403).send({success: false, msg: 'req.user._id not defined.'});
136
206
  // }
137
207
  winston.debug("hasRoleOrType req.user._id " +req.user._id);
138
- // project_user_qui_importante
139
-
140
- // JWT_HERE
141
- var query = { id_project: projectid, id_user: req.user._id, status: "active"};
142
- let cache_key = projectid+":project_users:iduser:"+req.user._id
143
-
144
- if (req.user.sub && (req.user.sub=="userexternal" || req.user.sub=="guest")) {
145
- query = { id_project: projectid, uuid_user: req.user._id, status: "active"};
146
- cache_key = projectid+":project_users:uuid_user:"+req.user._id
208
+ // project_user_qui_importante
209
+
210
+ var project_user = req.projectuser;
211
+ winston.debug("hasRoleOrTypes project_user hasRoleOrTypes", project_user);
212
+
213
+ if (!project_user) {
214
+ winston.debug("load project_user");
215
+ try {
216
+ project_user = await projectUserService.getWithPermissions(req.user._id, projectid, req.user.sub);
217
+ } catch(err) {
218
+ winston.error("Error getting project_user for hasrole",err);
219
+ return next(err);
220
+ }
221
+
222
+ winston.debug("project_user: ", JSON.stringify(project_user));
223
+
147
224
  }
148
- winston.debug("hasRoleOrType query " + JSON.stringify(query));
149
225
 
150
- let q = Project_user.findOne(query);
151
- if (cacheEnabler.project_user) {
152
- q.cache(cacheUtil.defaultTTL, cache_key);
153
- winston.debug("cacheEnabler.project_user enabled");
226
+ if (project_user) {
227
+
228
+ req.projectuser = project_user;
229
+ winston.debug("hasRoleOrTypes req.projectuser", req.projectuser.toJSON());
154
230
 
155
- }
156
- q.exec(function (err, project_user) {
157
- if (err) {
158
- winston.error("Error on Request path: " + req.originalUrl);
159
- winston.error("Error getting project_user for hasrole",err);
160
- return next(err);
161
- }
162
- winston.debug("project_user: ", JSON.stringify(project_user));
163
-
164
-
165
-
166
- if (project_user) {
167
-
168
- req.projectuser = project_user;
169
- winston.debug("req.projectuser", req.projectuser);
231
+ var userRole = project_user.role;
232
+ winston.debug("userRole", userRole);
170
233
 
171
- var userRole = project_user.role;
172
- winston.debug("userRole", userRole);
173
-
174
- if (!role) {
175
- next();
176
- }else {
177
-
178
- var hierarchicalRoles = that.ROLES[userRole];
179
- winston.debug("hierarchicalRoles", hierarchicalRoles);
180
-
181
- if ( hierarchicalRoles && hierarchicalRoles.includes(role)) {
182
- next();
183
- }else {
184
- res.status(403).send({success: false, msg: 'you dont have the required role.'});
185
- }
186
- }
187
- } else {
188
-
189
- /**
190
- * Updated by Johnny - 29mar2024 - START
191
- */
192
- // console.log("req.user: ", req.user);
193
- if (req.user.email === process.env.ADMIN_EMAIL) {
194
- req.user.attributes = { isSuperadmin: true };
234
+
235
+ if (!role) { //????
236
+ next();
237
+ }else {
238
+
239
+ var hierarchicalRoles = that.ROLES[userRole];
240
+ winston.debug("hierarchicalRoles", hierarchicalRoles);
241
+
242
+ if ( hierarchicalRoles ) { //standard role
243
+ winston.debug("standard role: "+ userRole);
244
+ if (hierarchicalRoles.includes(role)) {
195
245
  next();
196
246
  } else {
197
- res.status(403).send({success: false, msg: 'you dont belong to the project.'});
247
+ res.status(403).send({success: false, msg: 'you dont have the required role.'});
198
248
  }
199
- /**
200
- * Updated by Johnny - 29mar2024 - END
201
- */
249
+ } else { //custom role
250
+
251
+ winston.debug("custom role: "+ userRole);
252
+ return that.hasPermission(permission)(req, res, next);
202
253
 
203
- // if (req.user) equals super admin next()
204
- //res.status(403).send({success: false, msg: 'you dont belong to the project.'});
205
- }
206
-
207
- });
208
-
209
- }
210
-
211
- }
254
+ // if (permission==undefined) {
255
+ // winston.debug("permission is empty go next");
256
+ // return next();
257
+ // }
212
258
 
213
- // unused
214
- hasRoleAsPromise(role, user_id, projectid) {
259
+ // // invece di questo codice richiama hasPermission()
260
+ // var permissions = project_user._doc.rolePermissions;
215
261
 
216
- var that = this;
262
+ // winston.debug("hasPermission permissions", permissions);
263
+
264
+ // winston.debug("hasPermission permission: "+ permission);
217
265
 
218
- return new Promise(function (resolve, reject) {
219
- // project_user_qui_importante
266
+ // if (permissions!=undefined && permissions.length>0) {
267
+ // if (permissions.includes(permission)) {
268
+ // next();
269
+ // }else {
270
+ // res.status(403).send({success: false, msg: 'you dont have the required permission.'});
271
+ // }
272
+ // } else {
273
+ // res.status(403).send({success: false, msg: 'you dont have the required permission. Is is empty'});
274
+ // }
220
275
 
221
- // JWT_HERE
222
- var query = { id_project: req.params.projectid, id_user: req.user._id, status: "active"};
223
- if (req.user.sub && (req.user.sub=="userexternal" || req.user.sub=="guest")) {
224
- query = { id_project: req.params.projectid, uuid_user: req.user._id};
225
- }
226
276
 
227
- Project_user.find(query).
228
- exec(function (err, project_users) {
229
- if (err) {
230
- winston.error(err);
231
- return reject(err);
232
277
  }
233
-
234
-
235
- if (project_users && project_users.length>0) {
236
278
 
237
- var project_user= project_users[0];
279
+ }
280
+
281
+ } else {
282
+
283
+ /**
284
+ * Updated by Johnny - 29mar2024 - START
285
+ */
286
+ // console.log("req.user: ", req.user);
287
+ if (req.user.email === process.env.ADMIN_EMAIL) {
288
+ req.user.attributes = { isSuperadmin: true };
289
+ next();
290
+ } else {
291
+ res.status(403).send({success: false, msg: 'you dont belong to the project.'});
292
+ }
293
+ /**
294
+ * Updated by Johnny - 29mar2024 - END
295
+ */
238
296
 
239
- var userRole = project_user.role;
240
- // winston.debug("userRole", userRole);
241
-
242
- if (!role) {
243
- resolve(project_user);
244
- }else {
245
-
246
- var hierarchicalRoles = that.ROLES[userRole];
247
- // winston.debug("hierarchicalRoles", hierarchicalRoles);
248
-
249
- if ( hierarchicalRoles.includes(role)) {
250
- resolve(project_user);
251
- }else {
252
- reject({success: false, msg: 'you dont have the required role.'});
253
- }
254
- }
255
- } else {
256
-
257
- // if (req.user) equals super admin next()
258
- reject({success: false, msg: 'you dont belong to the project.'});
259
- }
260
-
261
- });
297
+ // if (req.user) equals super admin next()
298
+ //res.status(403).send({success: false, msg: 'you dont belong to the project.'});
299
+ }
262
300
 
263
- });
264
301
 
265
- }
266
-
302
+ }
303
+ }
304
+
267
305
  }
268
306
 
269
307
 
308
+
270
309
  var roleChecker = new RoleChecker();
271
310
  module.exports = roleChecker;
272
311