@xuda.io/notification_module 1.1.127 → 1.1.128
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/index.mjs +1 -5
- package/index.mjs.premerge.bak +668 -0
- package/package.json +1 -1
package/index.mjs
CHANGED
|
@@ -4,11 +4,7 @@ import admin from 'firebase-admin';
|
|
|
4
4
|
|
|
5
5
|
console.log('Notifications Module loaded...');
|
|
6
6
|
|
|
7
|
-
global._conf = (
|
|
8
|
-
await import(path.join(process.env.XUDA_HOME, process.env.XUDA_CONFIG), {
|
|
9
|
-
with: { type: 'json' },
|
|
10
|
-
})
|
|
11
|
-
).default;
|
|
7
|
+
global._conf = (await import(path.join(process.env.XUDA_HOME, "common", "load_conf.mjs"))).loadConf();
|
|
12
8
|
|
|
13
9
|
const _common = await import(path.join(process.env.XUDA_HOME, 'common', 'xuda_node_common.mjs'));
|
|
14
10
|
const module_path = path.join(process.env.XUDA_HOME, 'cpi') + (!_conf.is_debug ? '/node_modules/@xuda.io' : '');
|
|
@@ -0,0 +1,668 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import _ from 'lodash';
|
|
3
|
+
import admin from 'firebase-admin';
|
|
4
|
+
|
|
5
|
+
console.log('Notifications Module loaded...');
|
|
6
|
+
|
|
7
|
+
global._conf = (
|
|
8
|
+
await import(path.join(process.env.XUDA_HOME, process.env.XUDA_CONFIG), {
|
|
9
|
+
with: { type: 'json' },
|
|
10
|
+
})
|
|
11
|
+
).default;
|
|
12
|
+
|
|
13
|
+
const _common = await import(path.join(process.env.XUDA_HOME, 'common', 'xuda_node_common.mjs'));
|
|
14
|
+
const module_path = path.join(process.env.XUDA_HOME, 'cpi') + (!_conf.is_debug ? '/node_modules/@xuda.io' : '');
|
|
15
|
+
const db_module = await import(`${module_path}/db_module/index.mjs`);
|
|
16
|
+
|
|
17
|
+
const email_msa = await import(`${module_path}/email_module/index_msa.mjs`);
|
|
18
|
+
|
|
19
|
+
const ws_dashboard_msa = await import(`${module_path}/ws_dashboard_module/index_msa.mjs`);
|
|
20
|
+
|
|
21
|
+
//////////////////// FCM /////////////////////
|
|
22
|
+
const serviceAccount = _conf.firebase_serviceAccount;
|
|
23
|
+
admin.initializeApp({
|
|
24
|
+
credential: admin.credential.cert(serviceAccount),
|
|
25
|
+
databaseURL: 'https://your-project-id.firebaseio.com',
|
|
26
|
+
});
|
|
27
|
+
const messaging = admin.messaging();
|
|
28
|
+
//////////////////////////////////////////////
|
|
29
|
+
|
|
30
|
+
export const get_new_notification_count = async (req) => {
|
|
31
|
+
return await db_module.get_couch_view('xuda_notification', 'new_notifications_count', {
|
|
32
|
+
key: [req.uid],
|
|
33
|
+
reduce: true,
|
|
34
|
+
group_level: 1,
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const set_notification_read = async (req, job_id, header) => {
|
|
39
|
+
const ret = await db_module.get_couch_doc('xuda_notification', req.notification_id);
|
|
40
|
+
let notification_doc = ret.data;
|
|
41
|
+
|
|
42
|
+
if (notification_doc.system) {
|
|
43
|
+
return { code: -1, data: 'system notification not allow read' };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
notification_doc.read_date = Date.now();
|
|
47
|
+
notification_doc.read = true;
|
|
48
|
+
notification_doc.read_header = header;
|
|
49
|
+
return await db_module.save_couch_doc('xuda_notification', notification_doc);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export const update_notification_status = async (req) => {
|
|
53
|
+
const { notification_id, stat, uid } = req;
|
|
54
|
+
const ret = await db_module.get_couch_doc('xuda_notification', notification_id);
|
|
55
|
+
let notification_doc = ret.data;
|
|
56
|
+
notification_doc.stat_ts = Date.now();
|
|
57
|
+
notification_doc.stat = stat;
|
|
58
|
+
|
|
59
|
+
ws_dashboard_msa.notification({
|
|
60
|
+
to: notification_doc.system ? uid : notification_doc.uid,
|
|
61
|
+
data: notification_doc,
|
|
62
|
+
});
|
|
63
|
+
return await db_module.save_couch_doc('xuda_notification', notification_doc);
|
|
64
|
+
};
|
|
65
|
+
//, _ch= global[`_notification_module_ch`]
|
|
66
|
+
export const submit_notification = async (req) => {
|
|
67
|
+
try {
|
|
68
|
+
let { type, app_id, to_app_id, uid_arr, subject = '', body = '', delivery_method = [], display_type = 'info', ref, email, sender_uid, system, topic, params } = req;
|
|
69
|
+
let obj = {};
|
|
70
|
+
const { notification_categories } = await import(path.join(process.env.XUDA_HOME, 'notification_templates.mjs'));
|
|
71
|
+
|
|
72
|
+
let icon = 'https://dev.xuda.ai/dist/images/xuda_ico.png';
|
|
73
|
+
if (app_id) {
|
|
74
|
+
const app_id_reference = await _common.get_project_app_id(app_id, true);
|
|
75
|
+
const app_ret = await db_module.get_couch_doc('xuda_master', app_id_reference);
|
|
76
|
+
if (app_ret.code > -1) {
|
|
77
|
+
icon = app_ret.data.app_pic;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (!type) {
|
|
82
|
+
return { code: -1, data: 'error: type is mandatory field' };
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (topic) {
|
|
86
|
+
const _topic = notification_categories?.[type]?.topics?.[topic];
|
|
87
|
+
if (_topic) {
|
|
88
|
+
if (!subject) {
|
|
89
|
+
subject = _.template(_topic.subject)(params);
|
|
90
|
+
}
|
|
91
|
+
delivery_method = _topic.delivery_method;
|
|
92
|
+
display_type = _topic.display_type;
|
|
93
|
+
if (!body) {
|
|
94
|
+
body = _.template(_topic.body)(params);
|
|
95
|
+
}
|
|
96
|
+
} else {
|
|
97
|
+
return {
|
|
98
|
+
code: -1,
|
|
99
|
+
data: `${topic} topic for ${type} not exist in notification_categories`,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
let send_result = {};
|
|
105
|
+
|
|
106
|
+
for await (let uid of uid_arr) {
|
|
107
|
+
obj = {};
|
|
108
|
+
for await (let delivery_method_item of delivery_method) {
|
|
109
|
+
let account_ret;
|
|
110
|
+
if (!system) {
|
|
111
|
+
account_ret = await db_module.get_couch_doc('xuda_accounts', uid);
|
|
112
|
+
if (account_ret.code < 0) {
|
|
113
|
+
throw new Error(`user ${uid} not found`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
send_result[uid] = true;
|
|
117
|
+
const uuid = await _common.xuda_get_uuid('notification');
|
|
118
|
+
obj = {
|
|
119
|
+
_id: uuid,
|
|
120
|
+
docType: 'notification',
|
|
121
|
+
type,
|
|
122
|
+
app_id: to_app_id,
|
|
123
|
+
uid,
|
|
124
|
+
subject,
|
|
125
|
+
body,
|
|
126
|
+
delivery_method: delivery_method_item,
|
|
127
|
+
display_type,
|
|
128
|
+
read: false,
|
|
129
|
+
ref: ref || uuid,
|
|
130
|
+
date_created_ts: Date.now(),
|
|
131
|
+
date_created: Date.now(),
|
|
132
|
+
sender_uid,
|
|
133
|
+
stat: 3,
|
|
134
|
+
stat_ts: Date.now(),
|
|
135
|
+
system,
|
|
136
|
+
topic,
|
|
137
|
+
params,
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
switch (delivery_method_item) {
|
|
141
|
+
case 'email': {
|
|
142
|
+
// Honor an explicit email, else fall back to the recipient's account.
|
|
143
|
+
// System notifications skip the lookup above, so resolve it here
|
|
144
|
+
// (superuser alert recipients have real accounts with emails).
|
|
145
|
+
let resolved_email = email;
|
|
146
|
+
if (!resolved_email) {
|
|
147
|
+
if (!account_ret) {
|
|
148
|
+
account_ret = await db_module.get_couch_doc('xuda_accounts', uid).catch(() => null);
|
|
149
|
+
}
|
|
150
|
+
resolved_email = account_ret?.data?.account_info?.email || '';
|
|
151
|
+
}
|
|
152
|
+
obj.email = resolved_email;
|
|
153
|
+
if (!obj.email) {
|
|
154
|
+
send_result[uid] = false;
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
email_msa.send_email({
|
|
159
|
+
email: obj.email,
|
|
160
|
+
subject,
|
|
161
|
+
body,
|
|
162
|
+
ref: obj._id,
|
|
163
|
+
app_id: obj.app_id,
|
|
164
|
+
});
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
case 'banner':
|
|
169
|
+
case 'consent':
|
|
170
|
+
case 'alert':
|
|
171
|
+
ws_dashboard_msa.notification({
|
|
172
|
+
to: uid,
|
|
173
|
+
data: obj,
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
break;
|
|
177
|
+
case 'push':
|
|
178
|
+
try {
|
|
179
|
+
const ret = await db_module.find_couch_query('xuda_sessions', {
|
|
180
|
+
selector: {
|
|
181
|
+
docType: 'gtp_session',
|
|
182
|
+
stat: { $lt: 3 },
|
|
183
|
+
uid,
|
|
184
|
+
fcm_token: { $gt: '' },
|
|
185
|
+
},
|
|
186
|
+
});
|
|
187
|
+
let fcm_token_arr = [];
|
|
188
|
+
for await (let session of ret.docs) {
|
|
189
|
+
if (session.fcm_token) {
|
|
190
|
+
if (!fcm_token_arr.includes(session.fcm_token)) {
|
|
191
|
+
fcm_token_arr.push(session.fcm_token);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
for await (let fcm_token of fcm_token_arr) {
|
|
196
|
+
if (fcm_token) {
|
|
197
|
+
const message = {
|
|
198
|
+
notification: {
|
|
199
|
+
title: subject,
|
|
200
|
+
body,
|
|
201
|
+
image: icon,
|
|
202
|
+
},
|
|
203
|
+
token: fcm_token,
|
|
204
|
+
android: {
|
|
205
|
+
notification: {
|
|
206
|
+
imageUrl: icon,
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
apns: {
|
|
210
|
+
payload: {
|
|
211
|
+
aps: {
|
|
212
|
+
'mutable-content': 1,
|
|
213
|
+
},
|
|
214
|
+
},
|
|
215
|
+
fcm_options: {
|
|
216
|
+
image: icon,
|
|
217
|
+
},
|
|
218
|
+
},
|
|
219
|
+
webpush: {
|
|
220
|
+
headers: {
|
|
221
|
+
image: icon,
|
|
222
|
+
},
|
|
223
|
+
},
|
|
224
|
+
};
|
|
225
|
+
try {
|
|
226
|
+
messaging
|
|
227
|
+
.send(message)
|
|
228
|
+
.then((response) => {
|
|
229
|
+
// console.log("Successfully sent message:", response);
|
|
230
|
+
})
|
|
231
|
+
.catch((error) => {
|
|
232
|
+
console.error('Error sending message:', error);
|
|
233
|
+
});
|
|
234
|
+
} catch (err) {
|
|
235
|
+
console.error(err);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
} catch (err) {
|
|
240
|
+
console.error(err);
|
|
241
|
+
}
|
|
242
|
+
break;
|
|
243
|
+
|
|
244
|
+
default:
|
|
245
|
+
send_result[uid] = false;
|
|
246
|
+
break;
|
|
247
|
+
}
|
|
248
|
+
obj.sent = send_result[uid];
|
|
249
|
+
const ret = await db_module.save_couch_doc('xuda_notification', obj);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
return { code: 111, data: obj };
|
|
253
|
+
} catch (err) {
|
|
254
|
+
console.error(err);
|
|
255
|
+
return { code: -111, data: err.message };
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
export const get_notifications = async (req) => {
|
|
260
|
+
if (req.date_to < req.date_from) {
|
|
261
|
+
return {
|
|
262
|
+
code: -2,
|
|
263
|
+
data: 'error - invalid range date_from and date_to',
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
let selector = {
|
|
268
|
+
stat: 3,
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
if (req.outbox) {
|
|
272
|
+
selector.stat = { $lt: 4 };
|
|
273
|
+
selector.sender_uid = req.uid;
|
|
274
|
+
} else {
|
|
275
|
+
if (req.system) {
|
|
276
|
+
// Drop empty/undefined uid clauses (e.g. an unauthenticated/public call where
|
|
277
|
+
// req.uid is undefined, or to_app_id is ''), which otherwise build a malformed
|
|
278
|
+
// Mango $or and make find_couch_query throw -> 400.
|
|
279
|
+
selector.$or = [{ uid: req.uid }, { uid: 'system' }, { uid: req.to_app_id }].filter(
|
|
280
|
+
(clause) => typeof clause.uid === 'string' && clause.uid.length > 0,
|
|
281
|
+
);
|
|
282
|
+
} else {
|
|
283
|
+
if (!req.to_app_id) {
|
|
284
|
+
selector.uid = req.uid;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (req.date_to) {
|
|
290
|
+
selector.$and = [
|
|
291
|
+
{
|
|
292
|
+
date_created_ts: {
|
|
293
|
+
$lte: req.date_to,
|
|
294
|
+
$gte: req.date_from,
|
|
295
|
+
},
|
|
296
|
+
},
|
|
297
|
+
];
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
if (req.search) {
|
|
301
|
+
selector = {
|
|
302
|
+
...selector,
|
|
303
|
+
$or: [
|
|
304
|
+
{
|
|
305
|
+
body: {
|
|
306
|
+
$regex: `(?i)${req.search}`,
|
|
307
|
+
},
|
|
308
|
+
},
|
|
309
|
+
{
|
|
310
|
+
client_headers: {
|
|
311
|
+
$regex: `(?i)${req.search}`,
|
|
312
|
+
},
|
|
313
|
+
},
|
|
314
|
+
|
|
315
|
+
{
|
|
316
|
+
subject: {
|
|
317
|
+
$eq: req.search,
|
|
318
|
+
},
|
|
319
|
+
},
|
|
320
|
+
],
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
if (req.type) {
|
|
325
|
+
selector.type = req.type;
|
|
326
|
+
}
|
|
327
|
+
if (req.ref) {
|
|
328
|
+
selector.ref = req.ref;
|
|
329
|
+
}
|
|
330
|
+
if (typeof req.to_app_id !== 'undefined') {
|
|
331
|
+
selector.app_id = req.to_app_id;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
if (req.delivery_method) {
|
|
335
|
+
selector.delivery_method = req.delivery_method;
|
|
336
|
+
}
|
|
337
|
+
if (req.display_type) {
|
|
338
|
+
selector.display_type = req.display_type;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
if ((_.isBoolean(req.read) && req.read) || req.read == 'true') {
|
|
342
|
+
selector.read = true;
|
|
343
|
+
} else {
|
|
344
|
+
selector.read = false;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
if (typeof req.read === 'undefined') {
|
|
348
|
+
delete selector.read;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
const opt = {
|
|
352
|
+
selector,
|
|
353
|
+
|
|
354
|
+
sort: [
|
|
355
|
+
{
|
|
356
|
+
date_created_ts: 'desc',
|
|
357
|
+
},
|
|
358
|
+
],
|
|
359
|
+
limit: req.limit ? req.limit : 99999,
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
if (req.skip) {
|
|
363
|
+
opt.skip = req.skip;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
if (req?.bookmark !== 'nil') {
|
|
367
|
+
opt.bookmark = req.bookmark;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
try {
|
|
371
|
+
let ret = await db_module.find_couch_query('xuda_notification', opt);
|
|
372
|
+
let data = { docs: [] };
|
|
373
|
+
if (ret.docs) {
|
|
374
|
+
for await (let doc of ret.docs) {
|
|
375
|
+
if (await notifications_validation_fx(doc._id)) {
|
|
376
|
+
data.docs.push(doc);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
return {
|
|
382
|
+
code: 1,
|
|
383
|
+
data,
|
|
384
|
+
};
|
|
385
|
+
} catch (e) {
|
|
386
|
+
return {
|
|
387
|
+
code: -400,
|
|
388
|
+
data: e,
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
};
|
|
392
|
+
|
|
393
|
+
export const submit_superuser_notification = async (req) => {
|
|
394
|
+
const { uid, type, subject, delivery_method, body, display_type, to_uid = [], to_app_id, app_id, system } = req;
|
|
395
|
+
try {
|
|
396
|
+
if (!_conf.superuser_account_ids.includes(uid)) {
|
|
397
|
+
throw new Error('user is not authorized for this method');
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
if (!_.isArray(to_uid)) {
|
|
401
|
+
throw new Error('to_uid must be in the form of an array');
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
if (_.isEmpty(to_uid)) {
|
|
405
|
+
if (!system) {
|
|
406
|
+
const all_users = await db_module.find_couch_query('xuda_accounts', {
|
|
407
|
+
selector: {
|
|
408
|
+
docType: 'account',
|
|
409
|
+
stat: { $lt: 4 },
|
|
410
|
+
},
|
|
411
|
+
});
|
|
412
|
+
for await (let user of all_users.docs) {
|
|
413
|
+
to_uid.push(user._id);
|
|
414
|
+
}
|
|
415
|
+
} else {
|
|
416
|
+
to_uid.push('system');
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
let msg_obj = {
|
|
421
|
+
type,
|
|
422
|
+
uid_arr: to_uid,
|
|
423
|
+
app_id,
|
|
424
|
+
to_app_id: '',
|
|
425
|
+
subject,
|
|
426
|
+
body,
|
|
427
|
+
delivery_method: [delivery_method],
|
|
428
|
+
display_type,
|
|
429
|
+
sender_uid: uid,
|
|
430
|
+
ref: '',
|
|
431
|
+
system,
|
|
432
|
+
};
|
|
433
|
+
|
|
434
|
+
return submit_notification(msg_obj);
|
|
435
|
+
} catch (err) {
|
|
436
|
+
return { code: -1, data: err.message };
|
|
437
|
+
}
|
|
438
|
+
};
|
|
439
|
+
|
|
440
|
+
// Ops/admin alert for the AI error resolver. Renders the `error_resolver`
|
|
441
|
+
// template (notification_templates.mjs -> system category) and delivers to the
|
|
442
|
+
// superuser accounts (which have real emails) via the standard notification path.
|
|
443
|
+
export const submit_error_resolver_alert = async (req) => {
|
|
444
|
+
const { params = {} } = req || {};
|
|
445
|
+
try {
|
|
446
|
+
const recipients = _conf.superuser_account_ids || [];
|
|
447
|
+
if (!recipients.length) return { code: -1, data: 'no superuser recipients configured' };
|
|
448
|
+
return await submit_notification({
|
|
449
|
+
type: 'system',
|
|
450
|
+
topic: 'error_resolver',
|
|
451
|
+
uid_arr: recipients,
|
|
452
|
+
system: true,
|
|
453
|
+
params,
|
|
454
|
+
});
|
|
455
|
+
} catch (err) {
|
|
456
|
+
return { code: -1, data: err.message };
|
|
457
|
+
}
|
|
458
|
+
};
|
|
459
|
+
|
|
460
|
+
export const submit_app_notification = async (req) => {
|
|
461
|
+
const { uid, subject, delivery_method, body, display_type, to_uid = [], to_app_id, app_id, system, type } = req;
|
|
462
|
+
try {
|
|
463
|
+
if (!_.isArray(to_uid)) {
|
|
464
|
+
throw new Error('to_uid must be in the form of an array');
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
if (_.isEmpty(to_uid)) {
|
|
468
|
+
if (!system) {
|
|
469
|
+
throw new Error('to_uid is empty');
|
|
470
|
+
} else {
|
|
471
|
+
to_uid.push(app_id);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
const app_module = await import(`${module_path}/app_module/index.mjs`);
|
|
476
|
+
const users_arr = (
|
|
477
|
+
await app_module.get_app_users({
|
|
478
|
+
app_id_query: to_app_id,
|
|
479
|
+
})
|
|
480
|
+
).data;
|
|
481
|
+
const exists = _.some(to_uid, (val) => _.includes(users_arr, val));
|
|
482
|
+
if (!exists) {
|
|
483
|
+
throw new Error("some of the uid's are not authorized for the selected app");
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
let msg_obj = {
|
|
487
|
+
type: _conf.superuser_account_ids.includes(uid) && type ? type : 'user',
|
|
488
|
+
uid_arr: to_uid,
|
|
489
|
+
app_id,
|
|
490
|
+
to_app_id: to_app_id,
|
|
491
|
+
subject,
|
|
492
|
+
body,
|
|
493
|
+
delivery_method: [delivery_method],
|
|
494
|
+
display_type,
|
|
495
|
+
sender_uid: uid,
|
|
496
|
+
ref: '',
|
|
497
|
+
system,
|
|
498
|
+
};
|
|
499
|
+
|
|
500
|
+
return submit_notification(msg_obj);
|
|
501
|
+
} catch (err) {
|
|
502
|
+
return { code: -1, data: err.message };
|
|
503
|
+
}
|
|
504
|
+
};
|
|
505
|
+
|
|
506
|
+
export const update_system_notification = async (req) => {
|
|
507
|
+
const { display_type, subject, body, delivery_method, uid, type } = req;
|
|
508
|
+
const ret = await db_module.get_couch_doc('xuda_notification', req._id);
|
|
509
|
+
let notification_doc = ret.data;
|
|
510
|
+
|
|
511
|
+
if (!notification_doc.system) {
|
|
512
|
+
return { code: -1, data: 'only system notification allow update' };
|
|
513
|
+
}
|
|
514
|
+
const allowed_delivery_methods = ['banner', 'alert'];
|
|
515
|
+
if (!allowed_delivery_methods.includes(delivery_method)) {
|
|
516
|
+
return {
|
|
517
|
+
code: -1,
|
|
518
|
+
data: `only ${allowed_delivery_methods.toString()} delivery method allow update`,
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
notification_doc.ts = Date.now();
|
|
523
|
+
notification_doc.delivery_method = delivery_method;
|
|
524
|
+
notification_doc.display_type = display_type;
|
|
525
|
+
notification_doc.subject = subject;
|
|
526
|
+
notification_doc.body = body;
|
|
527
|
+
if (_conf.superuser_account_ids.includes(uid)) {
|
|
528
|
+
notification_doc.type = type;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
ws_dashboard_msa.notification({
|
|
532
|
+
to: notification_doc.system ? uid : notification_doc.uid,
|
|
533
|
+
data: notification_doc,
|
|
534
|
+
});
|
|
535
|
+
|
|
536
|
+
return await db_module.save_couch_doc('xuda_notification', notification_doc);
|
|
537
|
+
};
|
|
538
|
+
|
|
539
|
+
export const submit_topic_app_notification = async (req) => {
|
|
540
|
+
//, _ch
|
|
541
|
+
const { uid, topic, to_uid = [], to_app_id, app_id, system, type, params } = req;
|
|
542
|
+
try {
|
|
543
|
+
if (!_.isArray(to_uid)) {
|
|
544
|
+
throw new Error('to_uid must be in the form of an array');
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
if (_.isEmpty(to_uid)) {
|
|
548
|
+
if (!system) {
|
|
549
|
+
const app_module = await import(`${module_path}/app_module/index.mjs`);
|
|
550
|
+
const users_arr = (
|
|
551
|
+
await app_module.get_app_users({
|
|
552
|
+
app_id_query: to_app_id,
|
|
553
|
+
})
|
|
554
|
+
).data;
|
|
555
|
+
for await (let user_id of users_arr) {
|
|
556
|
+
if (uid !== user_id) {
|
|
557
|
+
to_uid.push(user_id);
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
} else {
|
|
561
|
+
to_uid.push(app_id);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
let msg_obj = {
|
|
566
|
+
type: type || 'user',
|
|
567
|
+
uid_arr: to_uid,
|
|
568
|
+
app_id,
|
|
569
|
+
to_app_id: to_app_id,
|
|
570
|
+
topic,
|
|
571
|
+
sender_uid: uid,
|
|
572
|
+
ref: '',
|
|
573
|
+
system,
|
|
574
|
+
params,
|
|
575
|
+
};
|
|
576
|
+
|
|
577
|
+
return submit_notification(msg_obj); //, _ch
|
|
578
|
+
} catch (err) {
|
|
579
|
+
return { code: -1, data: err.message };
|
|
580
|
+
}
|
|
581
|
+
};
|
|
582
|
+
|
|
583
|
+
export const get_system_notifications = async (req) => {
|
|
584
|
+
req.system = true;
|
|
585
|
+
req.to_app_id = '';
|
|
586
|
+
req.read = false;
|
|
587
|
+
// System notifications are non-critical app-init data fetched on every page load
|
|
588
|
+
// (including unauthenticated ones). A DB/query failure must never surface as a 400
|
|
589
|
+
// to the client (it stalls the loader) -> degrade to an empty list.
|
|
590
|
+
const ret = await get_notifications(req);
|
|
591
|
+
if (!ret || ret.code < 0) {
|
|
592
|
+
return { code: 1, data: { docs: [] } };
|
|
593
|
+
}
|
|
594
|
+
return ret;
|
|
595
|
+
};
|
|
596
|
+
|
|
597
|
+
|
|
598
|
+
export const notifications_validation_fx = async (notification_id) => {
|
|
599
|
+
let { code, data: doc } = await db_module.get_couch_doc('xuda_notification', notification_id);
|
|
600
|
+
const delete_notification = async () => {
|
|
601
|
+
doc.stat = 4;
|
|
602
|
+
await db_module.save_couch_doc('xuda_notification', doc);
|
|
603
|
+
};
|
|
604
|
+
const read_notification = async () => {
|
|
605
|
+
doc.read = true;
|
|
606
|
+
doc.read_ts = Date.now();
|
|
607
|
+
doc.read_note = 'read by notifications_validation_fx';
|
|
608
|
+
await db_module.save_couch_doc('xuda_notification', doc);
|
|
609
|
+
};
|
|
610
|
+
|
|
611
|
+
if (code < 0) return false;
|
|
612
|
+
|
|
613
|
+
if (!doc.topic) {
|
|
614
|
+
await delete_notification();
|
|
615
|
+
return false;
|
|
616
|
+
}
|
|
617
|
+
const fx = {
|
|
618
|
+
new_version_available: async () => {
|
|
619
|
+
const { code, data: app_doc } = await db_module.get_app_obj(doc.app_id);
|
|
620
|
+
if (app_doc.app_build_id >= doc.params.build) {
|
|
621
|
+
await read_notification();
|
|
622
|
+
return false;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
return true;
|
|
626
|
+
},
|
|
627
|
+
};
|
|
628
|
+
|
|
629
|
+
if (!fx[doc.topic]) {
|
|
630
|
+
return true;
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
return await fx[doc.topic]();
|
|
634
|
+
};
|
|
635
|
+
|
|
636
|
+
// setTimeout(async () => {
|
|
637
|
+
// // const app_id = "vps4d6ec68e01d97ef65a8bd86088b26ca2",
|
|
638
|
+
// // uid = "341cf2d32991a68e4d8aaba6c16e15cc",
|
|
639
|
+
// // ip = "192.11.22.333",
|
|
640
|
+
// // name = "Boaz Avrahami";
|
|
641
|
+
// // const aa = await module.exports.submit_notification({
|
|
642
|
+
// // type: "deploy",
|
|
643
|
+
// // app_id: app_id,
|
|
644
|
+
// // uid_arr: [uid],
|
|
645
|
+
// // topic: "welcome_aboard_vps",
|
|
646
|
+
// // params: {
|
|
647
|
+
// // name: name,
|
|
648
|
+
// // ip: ip,
|
|
649
|
+
// // dashboard_url: `https://xuda.ai/dashboard/project/${app_id}/admin/overview`,
|
|
650
|
+
// // dashboard_ssh_url: `https://xuda.ai/dashboard/project/${app_id}/admin/overview`,
|
|
651
|
+
// // dashboard_ssh_assign_url: `https://xuda.ai/dashboard/settings/ssh_keys`,
|
|
652
|
+
// // support_url: `https://xuda.ai/schedule/sales?topic=Sales&subtopic=General+Inquiries`,
|
|
653
|
+
// // },
|
|
654
|
+
// // ref: null,
|
|
655
|
+
// // email: null,
|
|
656
|
+
// // });
|
|
657
|
+
// // console.log(aa);
|
|
658
|
+
// }, 2000);
|
|
659
|
+
|
|
660
|
+
// class notifications_validation_class {
|
|
661
|
+
// constructor(name) {
|
|
662
|
+
// this.name = name;
|
|
663
|
+
// }
|
|
664
|
+
|
|
665
|
+
// new_version_available(params) {
|
|
666
|
+
// console.log(`Hello, my name is ${this.name}`);
|
|
667
|
+
// }
|
|
668
|
+
// }
|