@tiledesk/tiledesk-server 2.19.13 → 2.19.14
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 +3 -0
- package/channels/chat21/chat21WebHook.js +13 -2
- package/docs/activities-client.md +864 -0
- package/event/requestEvent.js +14 -0
- package/jobs.js +1 -0
- package/jobsManager.js +2 -0
- package/package.json +1 -1
- package/pubmodules/activities/activityArchiver.js +699 -377
- package/pubmodules/activities/activityMessageUtil.js +336 -0
- package/pubmodules/activities/index.js +1 -1
- package/pubmodules/activities/models/activity.js +99 -2
- package/pubmodules/activities/routes/activity.js +114 -144
- package/pubmodules/messageActions/messageActionsInterceptor.js +15 -2
- package/pubmodules/queue/reconnect.js +307 -2
- package/pubmodules/rules/conciergeBot.js +7 -1
- package/pubmodules/trigger/rulesTrigger.js +33 -5
- package/routes/faq_kb.js +24 -1
- package/routes/kb.js +90 -2
- package/routes/project_user.js +66 -17
- package/routes/request.js +20 -8
- package/services/chatbotService.js +6 -3
- package/services/requestService.js +159 -11
- package/test/faqkbRoute.js +1 -0
- package/test/kbRoute.js +59 -0
- package/utils/activityActorUtil.js +167 -0
- package/utils/assignmentContextUtil.js +283 -0
- package/utils/projectUserUpdateContextUtil.js +325 -0
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const projectUserUpdateContextUtil = require('./projectUserUpdateContextUtil');
|
|
4
|
+
const winston = require('../config/winston');
|
|
5
|
+
|
|
6
|
+
function systemActor() {
|
|
7
|
+
return { type: 'system', id: 'system', name: 'System' };
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function actorFromUser(user) {
|
|
11
|
+
return projectUserUpdateContextUtil.actorFromPrincipal(user);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function assignmentActorContext(req, defaultSource) {
|
|
15
|
+
const source = defaultSource || 'api';
|
|
16
|
+
|
|
17
|
+
if (!req || !req.user) {
|
|
18
|
+
return { actor: systemActor(), source: 'system' };
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (projectUserUpdateContextUtil.isSubscriptionActor(req.user)) {
|
|
22
|
+
return { actor: systemActor(), source: 'subscription' };
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const actor = actorFromUser(req.user);
|
|
26
|
+
const isBot = projectUserUpdateContextUtil.isBotActor(req.user);
|
|
27
|
+
|
|
28
|
+
if (isBot && actor.type !== 'bot') {
|
|
29
|
+
winston.warn('assignmentActorContext bot principal resolved as non-bot actor', {
|
|
30
|
+
actor: actor,
|
|
31
|
+
principal_id: projectUserUpdateContextUtil.resolveUserId(req.user),
|
|
32
|
+
principal_name: req.user && req.user.name,
|
|
33
|
+
principal_type: req.user && req.user.type,
|
|
34
|
+
principal_subtype: req.user && req.user.subtype,
|
|
35
|
+
principal_sub: req.user && req.user.sub,
|
|
36
|
+
principal_model: req.user && req.user.constructor && req.user.constructor.modelName,
|
|
37
|
+
source: source,
|
|
38
|
+
url: req.originalUrl
|
|
39
|
+
});
|
|
40
|
+
} else {
|
|
41
|
+
winston.info('assignmentActorContext actor resolution', {
|
|
42
|
+
actor: actor,
|
|
43
|
+
principal_id: projectUserUpdateContextUtil.resolveUserId(req.user),
|
|
44
|
+
principal_name: req.user && req.user.name,
|
|
45
|
+
principal_type: req.user && req.user.type,
|
|
46
|
+
principal_subtype: req.user && req.user.subtype,
|
|
47
|
+
principal_sub: req.user && req.user.sub,
|
|
48
|
+
principal_model: req.user && req.user.constructor && req.user.constructor.modelName,
|
|
49
|
+
isBotActor: isBot,
|
|
50
|
+
source: source,
|
|
51
|
+
url: req.originalUrl
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return { actor: actor, source: source };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function reconcileAssignmentPayload(data) {
|
|
59
|
+
const source = (data && data.source) || 'system';
|
|
60
|
+
let actor = (data && data.actor) || systemActor();
|
|
61
|
+
|
|
62
|
+
if (source === 'subscription' || actor.type === 'system') {
|
|
63
|
+
return {
|
|
64
|
+
actor: systemActor(),
|
|
65
|
+
source: source === 'subscription' ? 'subscription' : source
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return { actor: actor, source: source };
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function isHumanParticipant(participantId) {
|
|
73
|
+
return participantId && !String(participantId).startsWith('bot_');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function filterHumanParticipants(participantIds) {
|
|
77
|
+
return (participantIds || []).filter(isHumanParticipant);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function isBotParticipant(participantId) {
|
|
81
|
+
return participantId && String(participantId).startsWith('bot_');
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function filterBotParticipants(participantIds) {
|
|
85
|
+
return (participantIds || []).filter(isBotParticipant);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function botIdFromParticipant(participantId) {
|
|
89
|
+
return String(participantId).replace('bot_', '');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function resolveBotName(requestComplete, botParticipantOrId) {
|
|
93
|
+
const botId = isBotParticipant(botParticipantOrId)
|
|
94
|
+
? botIdFromParticipant(botParticipantOrId)
|
|
95
|
+
: String(botParticipantOrId);
|
|
96
|
+
const bots = requestComplete && requestComplete.participatingBots;
|
|
97
|
+
if (Array.isArray(bots)) {
|
|
98
|
+
for (const bot of bots) {
|
|
99
|
+
const id = String(bot._id || bot.id);
|
|
100
|
+
if (id === botId) {
|
|
101
|
+
return bot.name || id;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return botId;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function resolveDepartmentName(requestComplete) {
|
|
109
|
+
const dep = requestComplete && requestComplete.department;
|
|
110
|
+
if (!dep) {
|
|
111
|
+
return undefined;
|
|
112
|
+
}
|
|
113
|
+
if (dep.name) {
|
|
114
|
+
return dep.name;
|
|
115
|
+
}
|
|
116
|
+
return dep._id ? String(dep._id) : undefined;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function deriveAssignmentType({ actor, assigneeIds, isUnassign }) {
|
|
120
|
+
if (isUnassign) {
|
|
121
|
+
return 'unassign';
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const humanAssignees = filterHumanParticipants(assigneeIds);
|
|
125
|
+
if (humanAssignees.length === 0) {
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (!actor || actor.type === 'system') {
|
|
130
|
+
return 'auto';
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const assigneeId = String(humanAssignees[0]);
|
|
134
|
+
if (String(actor.id) === assigneeId) {
|
|
135
|
+
return 'self_join';
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return 'manual_reassign';
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function verbFromAssignmentType(assignmentType) {
|
|
142
|
+
switch (assignmentType) {
|
|
143
|
+
case 'auto':
|
|
144
|
+
return 'REQUEST_ASSIGNED_AUTO';
|
|
145
|
+
case 'self_join':
|
|
146
|
+
return 'REQUEST_ASSIGNED_SELF';
|
|
147
|
+
case 'manual_reassign':
|
|
148
|
+
case 'manual_reassign_bot':
|
|
149
|
+
case 'manual_reassign_department':
|
|
150
|
+
return 'REQUEST_ASSIGNED_MANUAL';
|
|
151
|
+
case 'unassign':
|
|
152
|
+
return 'REQUEST_UNASSIGNED';
|
|
153
|
+
default:
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function buildSetParticipantsOptions(req, participants) {
|
|
159
|
+
const { actor, source } = assignmentActorContext(req, 'api');
|
|
160
|
+
|
|
161
|
+
if (!participants || participants.length === 0) {
|
|
162
|
+
return {
|
|
163
|
+
actor,
|
|
164
|
+
source,
|
|
165
|
+
assignmentType: 'unassign'
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const botParticipants = filterBotParticipants(participants);
|
|
170
|
+
const humanParticipants = filterHumanParticipants(participants);
|
|
171
|
+
|
|
172
|
+
if (botParticipants.length > 0 && humanParticipants.length === 0) {
|
|
173
|
+
return {
|
|
174
|
+
actor,
|
|
175
|
+
source,
|
|
176
|
+
assignmentType: 'manual_reassign_bot'
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return {
|
|
181
|
+
actor,
|
|
182
|
+
source,
|
|
183
|
+
assignmentType: deriveAssignmentType({
|
|
184
|
+
actor,
|
|
185
|
+
assigneeIds: participants,
|
|
186
|
+
isUnassign: false
|
|
187
|
+
})
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function buildAddParticipantOptions(req, member) {
|
|
192
|
+
const { actor, source } = assignmentActorContext(req, 'api');
|
|
193
|
+
|
|
194
|
+
return {
|
|
195
|
+
actor,
|
|
196
|
+
source,
|
|
197
|
+
assignmentType: deriveAssignmentType({
|
|
198
|
+
actor,
|
|
199
|
+
assigneeIds: [member],
|
|
200
|
+
isUnassign: false
|
|
201
|
+
})
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function buildRemoveParticipantOptions(req, member) {
|
|
206
|
+
if (!isHumanParticipant(member)) {
|
|
207
|
+
return { trackLeave: false };
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const { actor: reqActor, source } = assignmentActorContext(req, 'api');
|
|
211
|
+
const actor = req && req.user && String(reqActor.id) === String(member)
|
|
212
|
+
? reqActor
|
|
213
|
+
: { type: 'user', id: String(member), name: String(member) };
|
|
214
|
+
|
|
215
|
+
return {
|
|
216
|
+
actor,
|
|
217
|
+
source,
|
|
218
|
+
member,
|
|
219
|
+
trackLeave: true
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function buildLeaveParticipantOptions(source, member) {
|
|
224
|
+
if (!isHumanParticipant(member)) {
|
|
225
|
+
return { trackLeave: false };
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return {
|
|
229
|
+
actor: { type: 'user', id: String(member), name: String(member) },
|
|
230
|
+
source: source || 'webhook',
|
|
231
|
+
member,
|
|
232
|
+
trackLeave: true
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function buildAutoRouteOptions(req, source) {
|
|
237
|
+
const ctx = assignmentActorContext(req, source || 'api');
|
|
238
|
+
return {
|
|
239
|
+
actor: ctx.actor,
|
|
240
|
+
source: ctx.source,
|
|
241
|
+
assignmentType: 'auto'
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function buildDepartmentRouteOptions(req, source) {
|
|
246
|
+
const ctx = assignmentActorContext(req, source || 'api');
|
|
247
|
+
return {
|
|
248
|
+
actor: ctx.actor,
|
|
249
|
+
source: ctx.source,
|
|
250
|
+
assignmentType: 'manual_reassign_department'
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function buildInternalOptions(source, assignmentType) {
|
|
255
|
+
return {
|
|
256
|
+
actor: systemActor(),
|
|
257
|
+
source: source || 'system',
|
|
258
|
+
assignmentType: assignmentType || 'auto'
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
module.exports = {
|
|
263
|
+
systemActor,
|
|
264
|
+
actorFromUser,
|
|
265
|
+
assignmentActorContext,
|
|
266
|
+
reconcileAssignmentPayload,
|
|
267
|
+
isHumanParticipant,
|
|
268
|
+
filterHumanParticipants,
|
|
269
|
+
isBotParticipant,
|
|
270
|
+
filterBotParticipants,
|
|
271
|
+
botIdFromParticipant,
|
|
272
|
+
resolveBotName,
|
|
273
|
+
resolveDepartmentName,
|
|
274
|
+
deriveAssignmentType,
|
|
275
|
+
verbFromAssignmentType,
|
|
276
|
+
buildSetParticipantsOptions,
|
|
277
|
+
buildAddParticipantOptions,
|
|
278
|
+
buildRemoveParticipantOptions,
|
|
279
|
+
buildLeaveParticipantOptions,
|
|
280
|
+
buildAutoRouteOptions,
|
|
281
|
+
buildDepartmentRouteOptions,
|
|
282
|
+
buildInternalOptions
|
|
283
|
+
};
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const Subscription = require('../models/subscription');
|
|
4
|
+
const Faq_kb = require('../models/faq_kb');
|
|
5
|
+
|
|
6
|
+
function systemActor() {
|
|
7
|
+
return { type: 'system', id: 'system', name: 'System' };
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function userDisplayName(user) {
|
|
11
|
+
if (!user) {
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const fullName = user.fullName || user.fullname;
|
|
16
|
+
if (fullName && String(fullName).trim()) {
|
|
17
|
+
return String(fullName).trim();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const name = ((user.firstname || '') + ' ' + (user.lastname || '')).trim();
|
|
21
|
+
if (name) {
|
|
22
|
+
return name;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function resolveUserId(userRef) {
|
|
29
|
+
if (userRef === undefined || userRef === null) {
|
|
30
|
+
return '';
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (typeof userRef === 'string' || typeof userRef === 'number') {
|
|
34
|
+
return String(userRef);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (userRef._id) {
|
|
38
|
+
return String(userRef._id);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (userRef.id) {
|
|
42
|
+
return String(userRef.id);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return String(userRef);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function isBotActor(user) {
|
|
49
|
+
if (!user) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (user instanceof Faq_kb) {
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (user.constructor && user.constructor.modelName === 'faq_kb') {
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (user.sub === 'bot' || (typeof user.sub === 'string' && user.sub.endsWith('/bot'))) {
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (typeof user.aud === 'string' && user.aud.indexOf('/bots/') > -1) {
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (user.type === 'tilebot' || user.subtype === 'chatbot') {
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Cached/plain faq_kb payloads may miss type/subtype but still carry bot identity fields.
|
|
74
|
+
if (
|
|
75
|
+
user.slug &&
|
|
76
|
+
user.name &&
|
|
77
|
+
user.id_project &&
|
|
78
|
+
user.createdBy &&
|
|
79
|
+
!user.email &&
|
|
80
|
+
!user.firstname &&
|
|
81
|
+
!user.lastname
|
|
82
|
+
) {
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function botDisplayName(user) {
|
|
90
|
+
if (!user || !user.name) {
|
|
91
|
+
return undefined;
|
|
92
|
+
}
|
|
93
|
+
const name = String(user.name).trim();
|
|
94
|
+
return name || undefined;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function actorFromPrincipal(user) {
|
|
98
|
+
if (!user) {
|
|
99
|
+
return systemActor();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (isSubscriptionActor(user)) {
|
|
103
|
+
return systemActor();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (isBotActor(user)) {
|
|
107
|
+
const id = resolveUserId(user);
|
|
108
|
+
return {
|
|
109
|
+
type: 'bot',
|
|
110
|
+
id: id,
|
|
111
|
+
name: botDisplayName(user) || id
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return {
|
|
116
|
+
type: 'user',
|
|
117
|
+
id: resolveUserId(user),
|
|
118
|
+
name: user.fullName || user.fullname || userDisplayName(user) || undefined
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function isSubscriptionActor(user) {
|
|
123
|
+
if (!user) {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (user instanceof Subscription) {
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (user.constructor && user.constructor.modelName === 'subscription') {
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Webhook subscription document (no user profile fields)
|
|
136
|
+
return Boolean(
|
|
137
|
+
user.event &&
|
|
138
|
+
user.target &&
|
|
139
|
+
user.id_project &&
|
|
140
|
+
user.createdBy &&
|
|
141
|
+
!user.email &&
|
|
142
|
+
!user.firstname &&
|
|
143
|
+
!user.lastname
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function isSystemAvailabilityInitiator(req) {
|
|
148
|
+
if (!req || !req.body) {
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return req.body.availabilityInitiator === 'system';
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function isAvailabilityUpdate(body) {
|
|
156
|
+
if (!body) {
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
return body.user_available !== undefined || body.profileStatus !== undefined;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function buildProjectUserUpdateContext(req, previousUserAvailable, previousProfileStatus, targetUserId) {
|
|
163
|
+
const context = {
|
|
164
|
+
previousUserAvailable,
|
|
165
|
+
previousProfileStatus,
|
|
166
|
+
source: 'api',
|
|
167
|
+
updateType: 'admin'
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
if (!req || !req.user) {
|
|
171
|
+
context.source = 'system';
|
|
172
|
+
context.updateType = 'system';
|
|
173
|
+
return context;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (isSubscriptionActor(req.user) || isSystemAvailabilityInitiator(req)) {
|
|
177
|
+
context.source = isSubscriptionActor(req.user) ? 'subscription' : 'api';
|
|
178
|
+
context.updateType = 'system';
|
|
179
|
+
return context;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const actorUserId = resolveUserId(req.user);
|
|
183
|
+
const targetId = resolveUserId(targetUserId);
|
|
184
|
+
const isSelfRoute = !req.params || !req.params.project_userid;
|
|
185
|
+
|
|
186
|
+
if (isSelfRoute) {
|
|
187
|
+
context.updateType = 'self';
|
|
188
|
+
return context;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (actorUserId && targetId && actorUserId === targetId) {
|
|
192
|
+
context.updateType = 'self';
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return context;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function actorFromUpdateContext(req, updateContext) {
|
|
199
|
+
if (
|
|
200
|
+
!req ||
|
|
201
|
+
!req.user ||
|
|
202
|
+
(updateContext && updateContext.updateType === 'system') ||
|
|
203
|
+
isSubscriptionActor(req.user) ||
|
|
204
|
+
isSystemAvailabilityInitiator(req)
|
|
205
|
+
) {
|
|
206
|
+
return systemActor();
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return {
|
|
210
|
+
type: 'user',
|
|
211
|
+
id: resolveUserId(req.user),
|
|
212
|
+
name: userDisplayName(req.user)
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function actorFromProjectUserUpdate(event, verb, updateContext) {
|
|
217
|
+
const actor = actorFromUpdateContext(event.req, updateContext);
|
|
218
|
+
|
|
219
|
+
if (actor.name) {
|
|
220
|
+
return actor;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const project_user = event.updatedProject_userPopulated;
|
|
224
|
+
const targetUser = project_user && project_user.id_user;
|
|
225
|
+
const targetName = userDisplayName(targetUser);
|
|
226
|
+
|
|
227
|
+
if (
|
|
228
|
+
targetName &&
|
|
229
|
+
(verb === 'PROJECT_USER_AVAILABILITY_SELF' ||
|
|
230
|
+
resolveUserId(targetUser) === actor.id)
|
|
231
|
+
) {
|
|
232
|
+
return Object.assign({}, actor, { name: targetName });
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return actor;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function verbForProjectUserUpdate(body, updateContext) {
|
|
239
|
+
if (!isAvailabilityUpdate(body)) {
|
|
240
|
+
return 'PROJECT_USER_UPDATE';
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (updateContext && updateContext.updateType === 'system') {
|
|
244
|
+
return 'PROJECT_USER_AVAILABILITY_SYSTEM';
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
if (updateContext && updateContext.updateType === 'self') {
|
|
248
|
+
return 'PROJECT_USER_AVAILABILITY_SELF';
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
return 'PROJECT_USER_UPDATE';
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function availabilityStatusLabel({ user_available, profileStatus }) {
|
|
255
|
+
if (profileStatus !== undefined && profileStatus !== null && profileStatus !== '') {
|
|
256
|
+
return String(profileStatus);
|
|
257
|
+
}
|
|
258
|
+
if (user_available === true) {
|
|
259
|
+
return 'available';
|
|
260
|
+
}
|
|
261
|
+
if (user_available === false) {
|
|
262
|
+
return 'unavailable';
|
|
263
|
+
}
|
|
264
|
+
return 'unknown';
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
function reconcileAvailabilityVerb(event, project_user, verb, updateContext) {
|
|
268
|
+
if (!isAvailabilityUpdate(event.req && event.req.body)) {
|
|
269
|
+
return { verb: verb, updateContext: updateContext, actor: null };
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
const context = Object.assign({}, updateContext);
|
|
273
|
+
let resolvedVerb = verb;
|
|
274
|
+
const targetUserId = resolveUserId(project_user && project_user.id_user);
|
|
275
|
+
const actorUserId = resolveUserId(event.req && event.req.user);
|
|
276
|
+
|
|
277
|
+
if (isSubscriptionActor(event.req && event.req.user) || isSystemAvailabilityInitiator(event.req)) {
|
|
278
|
+
context.updateType = 'system';
|
|
279
|
+
context.source = isSubscriptionActor(event.req.user) ? 'subscription' : (context.source || 'api');
|
|
280
|
+
resolvedVerb = 'PROJECT_USER_AVAILABILITY_SYSTEM';
|
|
281
|
+
return {
|
|
282
|
+
verb: resolvedVerb,
|
|
283
|
+
updateContext: context,
|
|
284
|
+
actor: systemActor()
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
if (resolvedVerb === 'PROJECT_USER_AVAILABILITY_SELF' && targetUserId && actorUserId && actorUserId !== targetUserId) {
|
|
289
|
+
context.updateType = 'admin';
|
|
290
|
+
resolvedVerb = 'PROJECT_USER_UPDATE';
|
|
291
|
+
return { verb: resolvedVerb, updateContext: context, actor: null };
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
return { verb: resolvedVerb, updateContext: context, actor: null };
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
function verbFromAvailabilityUpdateType(updateType) {
|
|
298
|
+
switch (updateType) {
|
|
299
|
+
case 'system':
|
|
300
|
+
return 'PROJECT_USER_AVAILABILITY_SYSTEM';
|
|
301
|
+
case 'self':
|
|
302
|
+
return 'PROJECT_USER_AVAILABILITY_SELF';
|
|
303
|
+
default:
|
|
304
|
+
return 'PROJECT_USER_UPDATE';
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
module.exports = {
|
|
309
|
+
systemActor,
|
|
310
|
+
userDisplayName,
|
|
311
|
+
resolveUserId,
|
|
312
|
+
isBotActor,
|
|
313
|
+
botDisplayName,
|
|
314
|
+
actorFromPrincipal,
|
|
315
|
+
isSubscriptionActor,
|
|
316
|
+
isSystemAvailabilityInitiator,
|
|
317
|
+
isAvailabilityUpdate,
|
|
318
|
+
buildProjectUserUpdateContext,
|
|
319
|
+
actorFromUpdateContext,
|
|
320
|
+
actorFromProjectUserUpdate,
|
|
321
|
+
verbForProjectUserUpdate,
|
|
322
|
+
availabilityStatusLabel,
|
|
323
|
+
reconcileAvailabilityVerb,
|
|
324
|
+
verbFromAvailabilityUpdateType
|
|
325
|
+
};
|