@app-connect/core 0.0.3 → 1.6.4

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.js CHANGED
@@ -1,1202 +1,1302 @@
1
- const express = require('express');
2
- const cors = require('cors')
3
- const bodyParser = require('body-parser');
4
- const dynamoose = require('dynamoose');
5
- const axios = require('axios');
6
- const { UserModel } = require('./models/userModel');
7
- const { CallLogModel } = require('./models/callLogModel');
8
- const { MessageLogModel } = require('./models/messageLogModel');
9
- const { AdminConfigModel } = require('./models/adminConfigModel');
10
- const { CacheModel } = require('./models/cacheModel');
11
- const jwt = require('./lib/jwt');
12
- const logCore = require('./handlers/log');
13
- const contactCore = require('./handlers/contact');
14
- const authCore = require('./handlers/auth');
15
- const adminCore = require('./handlers/admin');
16
- const userCore = require('./handlers/user');
17
- const dispositionCore = require('./handlers/disposition');
18
- const mock = require('./adapter/mock');
19
- const releaseNotes = require('./releaseNotes.json');
20
- const analytics = require('./lib/analytics');
21
- const util = require('./lib/util');
22
- const adapterRegistry = require('./adapter/registry');
23
-
24
- let packageJson = null;
25
- try {
26
- packageJson = require('./package.json');
27
- }
28
- catch (e) {
29
- packageJson = require('../package.json');
30
- }
31
-
32
- // For using dynamodb in local env
33
- if (process.env.DYNAMODB_LOCALHOST) {
34
- dynamoose.aws.ddb.local(process.env.DYNAMODB_LOCALHOST);
35
- }
36
-
37
- axios.defaults.headers.common['Unified-CRM-Extension-Version'] = packageJson.version;
38
-
39
- async function initDB() {
40
- if (!process.env.DISABLE_SYNC_DB_TABLE) {
41
- console.log('creating db tables if not exist...');
42
- await UserModel.sync();
43
- await CallLogModel.sync();
44
- await MessageLogModel.sync();
45
- await AdminConfigModel.sync();
46
- await CacheModel.sync();
47
- }
48
- }
49
-
50
- function getAnalyticsVariablesInReqHeaders({ headers }) {
51
- const hashedExtensionId = headers['rc-extension-id'];
52
- const hashedAccountId = headers['rc-account-id'];
53
- const ip = headers['x-forwarded-for']?.split(',')?.find(i => !i.startsWith('10.'));
54
- const userAgent = headers['user-agent'];
55
- const author = headers['developer-author-name'];
56
- const eventAddedVia = headers['eventAddedVia'];
57
- return {
58
- hashedAccountId,
59
- hashedExtensionId,
60
- ip,
61
- userAgent,
62
- author,
63
- eventAddedVia
64
- }
65
- }
66
-
67
- // Create a router with all core routes
68
- function createCoreRouter() {
69
- const router = express.Router();
70
-
71
- // Move all app.get, app.post, etc. to router.get, router.post, etc.
72
- router.get('/releaseNotes', async function (req, res) {
73
- const globalReleaseNotes = releaseNotes;
74
- const adapterReleaseNotes = adapterRegistry.getReleaseNotes();
75
- const mergedReleaseNotes = {};
76
- const versions = Object.keys(adapterReleaseNotes);
77
- for (const version of versions) {
78
- mergedReleaseNotes[version] = {
79
- global: globalReleaseNotes[version].global,
80
- ...adapterReleaseNotes[version] ?? {}
81
- };
82
- }
83
- res.json(mergedReleaseNotes);
84
- });
85
-
86
- router.get('/crmManifest', (req, res) => {
87
- try {
88
- const platformName = req.query.platformName || 'default';
89
- const crmManifest = adapterRegistry.getManifest(platformName);
90
- if (crmManifest) {
91
- // Override app server url for local development
92
- if (process.env.OVERRIDE_APP_SERVER) {
93
- crmManifest.serverUrl = process.env.OVERRIDE_APP_SERVER;
94
- }
95
- // Override server side logging server url for local development
96
- if (process.env.OVERRIDE_SERVER_SIDE_LOGGING_SERVER && crmManifest.platforms) {
97
- Object.keys(crmManifest.platforms).forEach(platformName => {
98
- const platform = crmManifest.platforms[platformName];
99
- if (platform.serverSideLogging) {
100
- platform.serverSideLogging.url = process.env.OVERRIDE_SERVER_SIDE_LOGGING_SERVER;
101
- }
102
- });
103
- }
104
- if (!crmManifest.author?.name) {
105
- throw 'author name is required';
106
- }
107
- res.json(crmManifest);
108
- }
109
- else {
110
- res.status(400).send('Platform not found');
111
- }
112
- }
113
- catch (e) {
114
- res.status(400).send('Platform not found');
115
- }
116
- });
117
-
118
- router.get('/is-alive', (req, res) => {
119
- res.send(`OK`);
120
- });
121
-
122
- router.get('/authValidation', async (req, res) => {
123
- const requestStartTime = new Date().getTime();
124
- let platformName = null;
125
- let success = false;
126
- let validationPass = false;
127
- let reason = '';
128
- let statusCode = 200;
129
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
130
- try {
131
- const jwtToken = req.query.jwtToken;
132
- if (jwtToken) {
133
- const decodedToken = jwt.decodeJwt(jwtToken);
134
- if (!decodedToken) {
135
- res.status(400).send('Invalid JWT token');
136
- return;
137
- }
138
- const { id: userId, platform } = decodedToken;
139
- platformName = platform;
140
- const { successful, returnMessage, failReason, status } = await authCore.authValidation({ platform, userId });
141
- success = true;
142
- validationPass = successful;
143
- reason = failReason;
144
- statusCode = status;
145
- res.status(200).send({ successful, returnMessage });
146
- }
147
- else {
148
- res.status(400).send('Please go to Settings and authorize CRM platform');
149
- success = false;
150
- }
151
- }
152
- catch (e) {
153
- console.log(`platform: ${platformName} \n${e.stack}`);
154
- statusCode = e.response?.status ?? 'unknown';
155
- res.status(400).send(e);
156
- success = false;
157
- }
158
- const requestEndTime = new Date().getTime();
159
- analytics.track({
160
- eventName: 'Auth validation',
161
- interfaceName: 'authValidation',
162
- adapterName: platformName,
163
- rcAccountId: hashedAccountId,
164
- extensionId: hashedExtensionId,
165
- success,
166
- requestDuration: (requestEndTime - requestStartTime) / 1000,
167
- userAgent,
168
- ip,
169
- author,
170
- extras: {
171
- validationPass,
172
- reason,
173
- statusCode
174
- },
175
- eventAddedVia
176
- });
177
- });
178
-
179
- router.get('/serverVersionInfo', (req, res) => {
180
- const defaultCrmManifest = adapterRegistry.getManifest('default');
181
- res.send({ version: defaultCrmManifest?.version ?? 'unknown' });
182
- });
183
-
184
- router.post('/admin/settings', async function (req, res) {
185
- const requestStartTime = new Date().getTime();
186
- let success = false;
187
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
188
- try {
189
- const { isValidated, rcAccountId } = await adminCore.validateAdminRole({ rcAccessToken: req.query.rcAccessToken });
190
- const hashedRcAccountId = util.getHashValue(rcAccountId, process.env.HASH_KEY);
191
- if (isValidated) {
192
- await adminCore.upsertAdminSettings({ hashedRcAccountId, adminSettings: req.body.adminSettings });
193
- res.status(200).send('Admin settings updated');
194
- success = true;
195
- }
196
- else {
197
- res.status(401).send('Admin validation failed');
198
- success = false;
199
- }
200
- }
201
- catch (e) {
202
- console.log(`${e.stack}`);
203
- res.status(400).send(e);
204
- }
205
- const requestEndTime = new Date().getTime();
206
- analytics.track({
207
- eventName: 'Set admin settings',
208
- interfaceName: 'setAdminSettings',
209
- rcAccountId: hashedAccountId,
210
- extensionId: hashedExtensionId,
211
- success,
212
- requestDuration: (requestEndTime - requestStartTime) / 1000,
213
- userAgent,
214
- ip,
215
- author,
216
- eventAddedVia
217
- });
218
- });
219
-
220
- router.get('/admin/settings', async function (req, res) {
221
- const requestStartTime = new Date().getTime();
222
- let platformName = null;
223
- let success = false;
224
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
225
- try {
226
- const jwtToken = req.query.jwtToken;
227
- if (jwtToken) {
228
- const unAuthData = jwt.decodeJwt(jwtToken);
229
- platformName = unAuthData?.platform ?? 'Unknown';
230
- const user = await UserModel.findByPk(unAuthData?.id);
231
- if (!user) {
232
- res.status(400).send();
233
- }
234
- const { isValidated, rcAccountId } = await adminCore.validateAdminRole({ rcAccessToken: req.query.rcAccessToken });
235
- const hashedRcAccountId = util.getHashValue(rcAccountId, process.env.HASH_KEY);
236
- if (isValidated) {
237
- const adminSettings = await adminCore.getAdminSettings({ hashedRcAccountId });
238
- if (adminSettings) {
239
- res.status(200).send(adminSettings);
240
- }
241
- else {
242
- res.status(200).send({
243
- customAdapter: null,
244
- userSettings: {}
245
- });
246
- }
247
- success = true;
248
- }
249
- else {
250
- res.status(401).send('Admin validation failed');
251
- success = true;
252
- }
253
- }
254
- else {
255
- res.status(400).send('Please go to Settings and authorize CRM platform');
256
- success = false;
257
- }
258
- }
259
- catch (e) {
260
- res.status(400).send(e);
261
- }
262
- const requestEndTime = new Date().getTime();
263
- analytics.track({
264
- eventName: 'Get admin settings',
265
- interfaceName: 'getAdminSettings',
266
- adapterName: platformName,
267
- rcAccountId: hashedAccountId,
268
- extensionId: hashedExtensionId,
269
- success,
270
- requestDuration: (requestEndTime - requestStartTime) / 1000,
271
- userAgent,
272
- ip,
273
- author,
274
- eventAddedVia
275
- });
276
- });
277
-
278
- router.get('/admin/serverLoggingSettings', async function (req, res) {
279
- const requestStartTime = new Date().getTime();
280
- let platformName = null;
281
- let success = false;
282
- const jwtToken = req.query.jwtToken;
283
- if (!jwtToken) {
284
- res.status(400).send('Please go to Settings and authorize CRM platform');
285
- return;
286
- }
287
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
288
- try {
289
- const unAuthData = jwt.decodeJwt(jwtToken);
290
- if (!unAuthData?.id) {
291
- res.status(400).send('Please go to Settings and authorize CRM platform');
292
- return;
293
- }
294
- platformName = unAuthData?.platform ?? 'Unknown';
295
- const user = await UserModel.findByPk(unAuthData?.id);
296
- if (!user) {
297
- res.status(400).send('User not found');
298
- return;
299
- }
300
- const serverLoggingSettings = await adminCore.getServerLoggingSettings({ user });
301
- res.status(200).send(serverLoggingSettings);
302
- success = true;
303
- }
304
- catch (e) {
305
- console.log(`${e.stack}`);
306
- res.status(400).send(e);
307
- }
308
- const requestEndTime = new Date().getTime();
309
- analytics.track({
310
- eventName: 'Get server logging settings',
311
- interfaceName: 'getServerLoggingSettings',
312
- adapterName: platformName,
313
- rcAccountId: hashedAccountId,
314
- extensionId: hashedExtensionId,
315
- success,
316
- requestDuration: (requestEndTime - requestStartTime) / 1000,
317
- userAgent,
318
- ip,
319
- author,
320
- eventAddedVia
321
- });
322
- });
323
-
324
- router.post('/admin/serverLoggingSettings', async function (req, res) {
325
- const requestStartTime = new Date().getTime();
326
- let platformName = null;
327
- let success = false;
328
- const jwtToken = req.query.jwtToken;
329
- if (!jwtToken) {
330
- res.status(400).send('Please go to Settings and authorize CRM platform');
331
- return;
332
- }
333
- if (!req.body.additionalFieldValues) {
334
- res.status(400).send('Missing additionalFieldValues');
335
- return;
336
- }
337
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
338
- try {
339
- const unAuthData = jwt.decodeJwt(jwtToken);
340
- if (!unAuthData?.id) {
341
- res.status(400).send('Please go to Settings and authorize CRM platform');
342
- return;
343
- }
344
- platformName = unAuthData?.platform ?? 'Unknown';
345
- const user = await UserModel.findByPk(unAuthData?.id);
346
- if (!user) {
347
- res.status(400).send('User not found');
348
- return;
349
- }
350
- const serverLoggingSettings = await adminCore.updateServerLoggingSettings({ user, additionalFieldValues: req.body.additionalFieldValues });
351
- res.status(200).send(serverLoggingSettings);
352
- success = true;
353
- }
354
- catch (e) {
355
- console.log(`${e.stack}`);
356
- res.status(400).send(e);
357
- success = false;
358
- }
359
- const requestEndTime = new Date().getTime();
360
- analytics.track({
361
- eventName: 'Set server logging settings',
362
- interfaceName: 'setServerLoggingSettings',
363
- adapterName: platformName,
364
- rcAccountId: hashedAccountId,
365
- extensionId: hashedExtensionId,
366
- success,
367
- requestDuration: (requestEndTime - requestStartTime) / 1000,
368
- userAgent,
369
- ip,
370
- author,
371
- eventAddedVia
372
- });
373
- })
374
-
375
- router.get('/user/preloadSettings', async function (req, res) {
376
- try {
377
- const rcAccessToken = req.query.rcAccessToken;
378
- const rcAccountId = req.query.rcAccountId;
379
- if (rcAccessToken || rcAccountId) {
380
- const userSettings = await userCore.getUserSettingsByAdmin({ rcAccessToken, rcAccountId });
381
- res.status(200).send(userSettings);
382
- }
383
- else {
384
- res.status(400).send('Cannot find rc user login');
385
- }
386
- }
387
- catch (e) {
388
- console.log(`${e.stack}`);
389
- res.status(400).send(e);
390
- }
391
- }
392
- );
393
- router.get('/user/settings', async function (req, res) {
394
- const requestStartTime = new Date().getTime();
395
- let platformName = null;
396
- let success = false;
397
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
398
- try {
399
- const jwtToken = req.query.jwtToken;
400
- if (jwtToken) {
401
- const unAuthData = jwt.decodeJwt(jwtToken);
402
- platformName = unAuthData?.platform ?? 'Unknown';
403
- const user = await UserModel.findByPk(unAuthData?.id);
404
- if (!user) {
405
- res.status(400).send();
406
- }
407
- else {
408
- const rcAccessToken = req.query.rcAccessToken;
409
- const rcAccountId = req.query.rcAccountId;
410
- const userSettings = await userCore.getUserSettings({ user, rcAccessToken, rcAccountId });
411
- success = true;
412
- res.status(200).send(userSettings);
413
- }
414
- }
415
- else {
416
- success = false;
417
- res.status(400).send('Please go to Settings and authorize CRM platform');
418
- }
419
- }
420
- catch (e) {
421
- console.log(`platform: ${platformName} \n${e.stack}`);
422
- }
423
- const requestEndTime = new Date().getTime();
424
- analytics.track({
425
- eventName: 'Get user settings',
426
- interfaceName: 'getUserSettings',
427
- adapterName: platformName,
428
- rcAccountId: hashedAccountId,
429
- extensionId: hashedExtensionId,
430
- success,
431
- requestDuration: (requestEndTime - requestStartTime) / 1000,
432
- userAgent,
433
- ip,
434
- author,
435
- eventAddedVia
436
- });
437
- });
438
-
439
- router.post('/user/settings', async function (req, res) {
440
- const requestStartTime = new Date().getTime();
441
- let platformName = null;
442
- let success = false;
443
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
444
- try {
445
- const jwtToken = req.query.jwtToken;
446
- if (jwtToken) {
447
- const unAuthData = jwt.decodeJwt(jwtToken);
448
- platformName = unAuthData?.platform;
449
- if (!platformName) {
450
- res.status(400).send('Unknown platform');
451
- }
452
- const user = await UserModel.findByPk(unAuthData?.id);
453
- if (!user) {
454
- res.status(400).send();
455
- }
456
- const { userSettings } = await userCore.updateUserSettings({ user, userSettings: req.body.userSettings, platformName });
457
- res.status(200).send({ userSettings });
458
- success = true;
459
- }
460
- else {
461
- res.status(400).send('Please go to Settings and authorize CRM platform');
462
- success = false;
463
- }
464
- }
465
- catch (e) {
466
- console.log(`platform: ${platformName} \n${e.stack}`);
467
- }
468
- const requestEndTime = new Date().getTime();
469
- analytics.track({
470
- eventName: 'Set user settings',
471
- interfaceName: 'setUserSettings',
472
- adapterName: platformName,
473
- rcAccountId: hashedAccountId,
474
- extensionId: hashedExtensionId,
475
- success,
476
- requestDuration: (requestEndTime - requestStartTime) / 1000,
477
- userAgent,
478
- ip,
479
- author,
480
- eventAddedVia
481
- });
482
- });
483
-
484
- router.get('/hostname', async function (req, res) {
485
- try {
486
- const jwtToken = req.query.jwtToken;
487
- if (jwtToken) {
488
- const unAuthData = jwt.decodeJwt(jwtToken);
489
- const user = await UserModel.findByPk(unAuthData?.id);
490
- if (!user) {
491
- res.status(400).send();
492
- return;
493
- }
494
- res.status(200).send(user.hostname);
495
- }
496
- else {
497
- res.status(400).send('Please go to Settings and authorize CRM platform');
498
- }
499
- }
500
- catch (e) {
501
- console.log(`${e.stack}`);
502
- res.status(500).send(e);
503
- }
504
- })
505
-
506
- router.get('/oauth-callback', async function (req, res) {
507
- const requestStartTime = new Date().getTime();
508
- let platformName = null;
509
- let success = false;
510
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
511
- try {
512
- if (!req.query?.callbackUri || req.query.callbackUri === 'undefined') {
513
- throw 'Missing callbackUri';
514
- }
515
- platformName = req.query.state ?
516
- req.query.state.split('platform=')[1] :
517
- decodeURIComponent(req.originalUrl).split('state=')[1].split('&')[0].split('platform=')[1];
518
- const hostname = req.query.hostname;
519
- const tokenUrl = req.query.tokenUrl;
520
- if (!platformName) {
521
- throw 'Missing platform name';
522
- }
523
- const hasAuthCodeInCallbackUri = req.query.callbackUri.includes('code=');
524
- if (!hasAuthCodeInCallbackUri) {
525
- // eslint-disable-next-line no-param-reassign
526
- req.query.callbackUri = `${req.query.callbackUri}&code=${req.query.code}`;
527
- }
528
- const { userInfo, returnMessage } = await authCore.onOAuthCallback({
529
- platform: platformName,
530
- hostname,
531
- tokenUrl,
532
- callbackUri: req.query.callbackUri,
533
- apiUrl: req.query.apiUrl,
534
- username: req.query.username,
535
- query: req.query
536
- });
537
- if (userInfo) {
538
- const jwtToken = jwt.generateJwt({
539
- id: userInfo.id.toString(),
540
- platform: platformName
541
- });
542
- res.status(200).send({ jwtToken, name: userInfo.name, returnMessage });
543
- success = true;
544
- }
545
- else {
546
- res.status(200).send({ returnMessage });
547
- success = false;
548
- }
549
- }
550
- catch (e) {
551
- console.log(`platform: ${platformName} \n${e.stack}`);
552
- res.status(400).send(e);
553
- success = false;
554
- }
555
- const requestEndTime = new Date().getTime();
556
- analytics.track({
557
- eventName: 'OAuth Callback',
558
- interfaceName: 'onOAuthCallback',
559
- adapterName: platformName,
560
- rcAccountId: hashedAccountId,
561
- extensionId: hashedExtensionId,
562
- success,
563
- requestDuration: (requestEndTime - requestStartTime) / 1000,
564
- userAgent,
565
- ip,
566
- author,
567
- eventAddedVia
568
- });
569
- })
570
- router.post('/apiKeyLogin', async function (req, res) {
571
- const requestStartTime = new Date().getTime();
572
- let platformName = null;
573
- let success = false;
574
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
575
- try {
576
- const platform = req.body.platform;
577
- platformName = platform;
578
- const apiKey = req.body.apiKey;
579
- const hostname = req.body.hostname;
580
- const additionalInfo = req.body.additionalInfo;
581
- if (!platform) {
582
- throw 'Missing platform name';
583
- }
584
- if (!apiKey) {
585
- throw 'Missing api key';
586
- }
587
- const { userInfo, returnMessage } = await authCore.onApiKeyLogin({ platform, hostname, apiKey, additionalInfo });
588
- if (userInfo) {
589
- const jwtToken = jwt.generateJwt({
590
- id: userInfo.id.toString(),
591
- platform: platform
592
- });
593
- res.status(200).send({ jwtToken, name: userInfo.name, returnMessage });
594
- success = true;
595
- }
596
- else {
597
- res.status(400).send({ returnMessage });
598
- success = false;
599
- }
600
- }
601
- catch (e) {
602
- console.log(`platform: ${platformName} \n${e.stack}`);
603
- res.status(400).send(e);
604
- success = false;
605
- }
606
- const requestEndTime = new Date().getTime();
607
- analytics.track({
608
- eventName: 'API Key Login',
609
- interfaceName: 'onApiKeyLogin',
610
- adapterName: platformName,
611
- rcAccountId: hashedAccountId,
612
- extensionId: hashedExtensionId,
613
- success,
614
- requestDuration: (requestEndTime - requestStartTime) / 1000,
615
- userAgent,
616
- ip,
617
- author,
618
- eventAddedVia
619
- });
620
- })
621
- router.post('/unAuthorize', async function (req, res) {
622
- const requestStartTime = new Date().getTime();
623
- let platformName = null;
624
- let success = false;
625
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
626
- try {
627
- const jwtToken = req.query.jwtToken;
628
- if (jwtToken) {
629
- const unAuthData = jwt.decodeJwt(jwtToken);
630
- platformName = unAuthData?.platform ?? 'Unknown';
631
- const userToLogout = await UserModel.findByPk(unAuthData?.id);
632
- if (!userToLogout) {
633
- res.status(400).send();
634
- return;
635
- }
636
- const platformModule = adapterRegistry.getAdapter(unAuthData?.platform ?? 'Unknown');
637
- const { returnMessage } = await platformModule.unAuthorize({ user: userToLogout });
638
- res.status(200).send({ returnMessage });
639
- success = true;
640
- }
641
- else {
642
- res.status(400).send('Please go to Settings and authorize CRM platform');
643
- success = false;
644
- }
645
- }
646
- catch (e) {
647
- console.log(`platform: ${platformName} \n${e.stack}`);
648
- res.status(400).send(e);
649
- success = false;
650
- }
651
- const requestEndTime = new Date().getTime();
652
- analytics.track({
653
- eventName: 'Unauthorize',
654
- interfaceName: 'unAuthorize',
655
- adapterName: platformName,
656
- rcAccountId: hashedAccountId,
657
- extensionId: hashedExtensionId,
658
- success,
659
- requestDuration: (requestEndTime - requestStartTime) / 1000,
660
- userAgent,
661
- ip,
662
- author,
663
- eventAddedVia
664
- });
665
- });
666
- router.get('/userInfoHash', async function (req, res) {
667
- try {
668
- const extensionId = util.getHashValue(req.query.extensionId, process.env.HASH_KEY);
669
- const accountId = util.getHashValue(req.query.accountId, process.env.HASH_KEY);
670
- res.status(200).send({ extensionId, accountId });
671
- }
672
- catch (e) {
673
- console.log(`${e.stack}`);
674
- res.status(400).send(e);
675
- }
676
- })
677
- router.get('/contact', async function (req, res) {
678
- const requestStartTime = new Date().getTime();
679
- let platformName = null;
680
- let success = false;
681
- let resultCount = 0;
682
- let extraData = {};
683
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
684
- try {
685
- const jwtToken = req.query.jwtToken;
686
- if (jwtToken) {
687
- const decodedToken = jwt.decodeJwt(jwtToken);
688
- if (!decodedToken) {
689
- res.status(400).send('Please go to Settings and authorize CRM platform');
690
- return;
691
- }
692
- const { id: userId, platform } = decodedToken;
693
- platformName = platform;
694
- const { successful, returnMessage, contact, extraDataTracking } = await contactCore.findContact({ platform, userId, phoneNumber: req.query.phoneNumber.replace(' ', '+'), overridingFormat: req.query.overridingFormat, isExtension: req.query?.isExtension ?? false });
695
- res.status(200).send({ successful, returnMessage, contact });
696
- if (successful) {
697
- const nonNewContact = contact?.filter(c => !c.isNewContact) ?? [];
698
- resultCount = nonNewContact.length;
699
- }
700
- success = successful;
701
- if (extraDataTracking) {
702
- extraData = extraDataTracking;
703
- }
704
- }
705
- else {
706
- res.status(400).send('Please go to Settings and authorize CRM platform');
707
- success = false;
708
- }
709
- }
710
- catch (e) {
711
- console.log(`platform: ${platformName} \n${e.stack}`);
712
- extraData.statusCode = e.response?.status ?? 'unknown';
713
- res.status(400).send(e);
714
- success = false;
715
- }
716
- const requestEndTime = new Date().getTime();
717
- analytics.track({
718
- eventName: 'Find contact',
719
- interfaceName: 'findContact',
720
- adapterName: platformName,
721
- rcAccountId: hashedAccountId,
722
- extensionId: hashedExtensionId,
723
- success,
724
- requestDuration: (requestEndTime - requestStartTime) / 1000,
725
- userAgent,
726
- ip,
727
- author,
728
- extras: {
729
- resultCount,
730
- ...extraData
731
- },
732
- eventAddedVia
733
- });
734
- });
735
- router.post('/contact', async function (req, res) {
736
- const requestStartTime = new Date().getTime();
737
- let platformName = null;
738
- let success = false;
739
- let extraData = {};
740
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
741
- try {
742
- const jwtToken = req.query.jwtToken;
743
- if (jwtToken) {
744
- const decodedToken = jwt.decodeJwt(jwtToken);
745
- if (!decodedToken) {
746
- res.status(400).send('Please go to Settings and authorize CRM platform');
747
- return;
748
- }
749
- const { id: userId, platform } = decodedToken;
750
- platformName = platform;
751
- const { successful, returnMessage, contact, extraDataTracking } = await contactCore.createContact({ platform, userId, phoneNumber: req.body.phoneNumber, newContactName: req.body.newContactName, newContactType: req.body.newContactType, additionalSubmission: req.body.additionalSubmission });
752
- res.status(200).send({ successful, returnMessage, contact });
753
- success = true;
754
- if (extraDataTracking) {
755
- extraData = extraDataTracking;
756
- }
757
- }
758
- else {
759
- res.status(400).send('Please go to Settings and authorize CRM platform');
760
- success = false;
761
- }
762
- }
763
- catch (e) {
764
- console.log(`platform: ${platformName} \n${e.stack}`);
765
- extraData.statusCode = e.response?.status ?? 'unknown';
766
- res.status(400).send(e);
767
- success = false;
768
- }
769
- const requestEndTime = new Date().getTime();
770
- analytics.track({
771
- eventName: 'Create contact',
772
- interfaceName: 'createContact',
773
- adapterName: platformName,
774
- rcAccountId: hashedAccountId,
775
- extensionId: hashedExtensionId,
776
- success,
777
- requestDuration: (requestEndTime - requestStartTime) / 1000,
778
- userAgent,
779
- ip,
780
- author,
781
- extras: {
782
- ...extraData
783
- },
784
- eventAddedVia
785
- });
786
- });
787
- router.get('/callLog', async function (req, res) {
788
- const requestStartTime = new Date().getTime();
789
- let platformName = null;
790
- let success = false;
791
- let extraData = {};
792
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
793
- try {
794
- const jwtToken = req.query.jwtToken;
795
- if (jwtToken) {
796
- const decodedToken = jwt.decodeJwt(jwtToken);
797
- if (!decodedToken) {
798
- res.status(400).send('Please go to Settings and authorize CRM platform');
799
- return;
800
- }
801
- const { id: userId, platform } = decodedToken;
802
- platformName = platform;
803
- const { successful, logs, returnMessage, extraDataTracking } = await logCore.getCallLog({ userId, sessionIds: req.query.sessionIds, platform, requireDetails: req.query.requireDetails === 'true' });
804
- res.status(200).send({ successful, logs, returnMessage });
805
- success = true;
806
- if (extraDataTracking) {
807
- extraData = extraDataTracking;
808
- }
809
- }
810
- else {
811
- res.status(400).send('Please go to Settings and authorize CRM platform');
812
- success = false;
813
- }
814
- }
815
- catch (e) {
816
- console.log(`platform: ${platformName} \n${e.stack}`);
817
- extraData.statusCode = e.response?.status ?? 'unknown';
818
- res.status(400).send(e);
819
- success = false;
820
- }
821
- const requestEndTime = new Date().getTime();
822
- analytics.track({
823
- eventName: 'Get call log',
824
- interfaceName: 'getCallLog',
825
- adapterName: platformName,
826
- rcAccountId: hashedAccountId,
827
- extensionId: hashedExtensionId,
828
- success,
829
- requestDuration: (requestEndTime - requestStartTime) / 1000,
830
- userAgent,
831
- ip,
832
- author,
833
- extras: {
834
- ...extraData
835
- },
836
- eventAddedVia
837
- });
838
- });
839
- router.post('/callLog', async function (req, res) {
840
- const requestStartTime = new Date().getTime();
841
- let platformName = null;
842
- let success = false;
843
- let extraData = {};
844
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
845
- try {
846
- const jwtToken = req.query.jwtToken;
847
- if (jwtToken) {
848
- const decodedToken = jwt.decodeJwt(jwtToken);
849
- if (!decodedToken) {
850
- res.status(400).send('Please go to Settings and authorize CRM platform');
851
- return;
852
- }
853
- const { id: userId, platform } = decodedToken;
854
- platformName = platform;
855
- const { successful, logId, returnMessage, extraDataTracking } = await logCore.createCallLog({ platform, userId, incomingData: req.body });
856
- if (extraDataTracking) {
857
- extraData = extraDataTracking;
858
- }
859
- res.status(200).send({ successful, logId, returnMessage });
860
- success = true;
861
- }
862
- else {
863
- res.status(400).send('Please go to Settings and authorize CRM platform');
864
- success = false;
865
- }
866
- }
867
- catch (e) {
868
- console.log(`platform: ${platformName} \n${e.stack}`);
869
- extraData.statusCode = e.response?.status ?? 'unknown';
870
- res.status(400).send(e);
871
- success = false;
872
- }
873
- const requestEndTime = new Date().getTime();
874
- analytics.track({
875
- eventName: 'Create call log',
876
- interfaceName: 'createCallLog',
877
- adapterName: platformName,
878
- rcAccountId: hashedAccountId,
879
- extensionId: hashedExtensionId,
880
- success,
881
- requestDuration: (requestEndTime - requestStartTime) / 1000,
882
- userAgent,
883
- ip,
884
- author,
885
- extras: {
886
- ...extraData
887
- },
888
- eventAddedVia
889
- });
890
- });
891
- router.patch('/callLog', async function (req, res) {
892
- const requestStartTime = new Date().getTime();
893
- let platformName = null;
894
- let success = false;
895
- let extraData = {};
896
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
897
- try {
898
- const jwtToken = req.query.jwtToken;
899
- if (jwtToken) {
900
- const decodedToken = jwt.decodeJwt(jwtToken);
901
- if (!decodedToken) {
902
- res.status(400).send('Please go to Settings and authorize CRM platform');
903
- return;
904
- }
905
- const { id: userId, platform } = decodedToken;
906
- platformName = platform;
907
- const { successful, logId, updatedNote, returnMessage, extraDataTracking } = await logCore.updateCallLog({ platform, userId, incomingData: req.body });
908
- if (extraDataTracking) {
909
- extraData = extraDataTracking;
910
- }
911
- res.status(200).send({ successful, logId, updatedNote, returnMessage });
912
- success = true;
913
- }
914
- else {
915
- res.status(400).send('Please go to Settings and authorize CRM platform');
916
- success = false;
917
- }
918
- }
919
- catch (e) {
920
- console.log(`platform: ${platformName} \n${e.stack}`);
921
- extraData.statusCode = e.response?.status ?? 'unknown';
922
- res.status(400).send(e);
923
- success = false;
924
- }
925
- const requestEndTime = new Date().getTime();
926
- analytics.track({
927
- eventName: 'Update call log',
928
- interfaceName: 'updateCallLog',
929
- adapterName: platformName,
930
- rcAccountId: hashedAccountId,
931
- extensionId: hashedExtensionId,
932
- success,
933
- requestDuration: (requestEndTime - requestStartTime) / 1000,
934
- userAgent,
935
- ip,
936
- author,
937
- extras: {
938
- ...extraData
939
- },
940
- eventAddedVia
941
- });
942
- });
943
- router.put('/callDisposition', async function (req, res) {
944
- const requestStartTime = new Date().getTime();
945
- let platformName = null;
946
- let success = false;
947
- let extraData = {};
948
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
949
- try {
950
- const jwtToken = req.query.jwtToken;
951
- if (jwtToken) {
952
- const { id: userId, platform } = jwt.decodeJwt(jwtToken);
953
- platformName = platform;
954
- if (!userId) {
955
- res.status(400).send();
956
- }
957
- const { successful, returnMessage, extraDataTracking } = await dispositionCore.upsertCallDisposition({
958
- platform,
959
- userId,
960
- sessionId: req.body.sessionId,
961
- dispositions: req.body.dispositions,
962
- additionalSubmission: req.body.additionalSubmission
963
- });
964
- if (extraDataTracking) {
965
- extraData = extraDataTracking;
966
- }
967
- res.status(200).send({ successful, returnMessage });
968
- success = true;
969
- }
970
- else {
971
- res.status(400).send('Please go to Settings and authorize CRM platform');
972
- success = false;
973
- }
974
- }
975
- catch (e) {
976
- console.log(`platform: ${platformName} \n${e.stack}`);
977
- extraData.statusCode = e.response?.status ?? 'unknown';
978
- res.status(400).send(e);
979
- success = false;
980
- }
981
- const requestEndTime = new Date().getTime();
982
- analytics.track({
983
- eventName: 'Create call log',
984
- interfaceName: 'createCallLog',
985
- adapterName: platformName,
986
- rcAccountId: hashedAccountId,
987
- extensionId: hashedExtensionId,
988
- success,
989
- requestDuration: (requestEndTime - requestStartTime) / 1000,
990
- userAgent,
991
- ip,
992
- author,
993
- extras: {
994
- ...extraData
995
- },
996
- eventAddedVia
997
- });
998
- });
999
- router.post('/messageLog', async function (req, res) {
1000
- const requestStartTime = new Date().getTime();
1001
- let platformName = null;
1002
- let success = false;
1003
- let statusCode = 200;
1004
- let extraData = {};
1005
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
1006
- try {
1007
- const jwtToken = req.query.jwtToken;
1008
- if (jwtToken) {
1009
- const decodedToken = jwt.decodeJwt(jwtToken);
1010
- if (!decodedToken) {
1011
- res.status(400).send('Please go to Settings and authorize CRM platform');
1012
- return;
1013
- }
1014
- const { id: userId, platform } = decodedToken;
1015
- platformName = platform;
1016
- const { successful, returnMessage, logIds, extraDataTracking } = await logCore.createMessageLog({ platform, userId, incomingData: req.body });
1017
- if (extraDataTracking) {
1018
- extraData = extraDataTracking;
1019
- }
1020
- res.status(200).send({ successful, returnMessage, logIds });
1021
- success = true;
1022
- }
1023
- else {
1024
- res.status(400).send('Please go to Settings and authorize CRM platform');
1025
- success = false;
1026
- }
1027
- }
1028
- catch (e) {
1029
- console.log(`platform: ${platformName} \n${e.stack}`);
1030
- statusCode = e.response?.status ?? 'unknown';
1031
- res.status(400).send(e);
1032
- success = false;
1033
- }
1034
- const requestEndTime = new Date().getTime();
1035
- analytics.track({
1036
- eventName: 'Create message log',
1037
- interfaceName: 'createMessageLog',
1038
- adapterName: platformName,
1039
- rcAccountId: hashedAccountId,
1040
- extensionId: hashedExtensionId,
1041
- success,
1042
- requestDuration: (requestEndTime - requestStartTime) / 1000,
1043
- userAgent,
1044
- ip,
1045
- author,
1046
- extras: {
1047
- statusCode,
1048
- ...extraData
1049
- },
1050
- eventAddedVia
1051
- });
1052
- });
1053
-
1054
- router.get('/custom/contact/search', async function (req, res) {
1055
- const requestStartTime = new Date().getTime();
1056
- let platformName = null;
1057
- let success = false;
1058
- let resultCount = 0;
1059
- let statusCode = 200;
1060
- const { hashedExtensionId, hashedAccountId, userAgent, ip, author } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
1061
- try {
1062
- const jwtToken = req.query.jwtToken;
1063
- if (jwtToken) {
1064
- const { id: userId, platform } = jwt.decodeJwt(jwtToken);
1065
- platformName = platform;
1066
- const { successful, returnMessage, contact } = await contactCore.findContactWithName({ platform, userId, name: req.query.name });
1067
- res.status(200).send({ successful, returnMessage, contact });
1068
- success = successful;
1069
- }
1070
- else {
1071
- res.status(400).send('Please go to Settings and authorize CRM platform');
1072
- success = false;
1073
- }
1074
-
1075
- }
1076
- catch (e) {
1077
- console.log(`platform: ${platformName} \n${e.stack}`);
1078
- statusCode = e.response?.status ?? 'unknown';
1079
- res.status(400).send(e);
1080
- success = false;
1081
- }
1082
- const requestEndTime = new Date().getTime();
1083
- analytics.track({
1084
- eventName: 'Contact Search by Name',
1085
- interfaceName: 'contactSearchByName',
1086
- adapterName: platformName,
1087
- rcAccountId: hashedAccountId,
1088
- extensionId: hashedExtensionId,
1089
- success,
1090
- requestDuration: (requestEndTime - requestStartTime) / 1000,
1091
- userAgent,
1092
- ip,
1093
- author,
1094
- extras: {
1095
- statusCode
1096
- }
1097
- });
1098
-
1099
- });
1100
- if (process.env.IS_PROD === 'false') {
1101
- router.post('/registerMockUser', async function (req, res) {
1102
- const secretKey = req.query.secretKey;
1103
- if (secretKey === process.env.APP_SERVER_SECRET_KEY) {
1104
- const mockUser = await mock.createUser({ userName: req.body.userName });
1105
- res.status(200).send(mockUser ? 'Mock user registered' : 'Mock user already existed');
1106
- }
1107
- else {
1108
- res.status(401).send('Unauthorized');
1109
- }
1110
- });
1111
- router.delete('/deleteMockUser', async function (req, res) {
1112
- const secretKey = req.query.secretKey;
1113
- if (secretKey === process.env.APP_SERVER_SECRET_KEY) {
1114
- const foundAndDeleted = await mock.deleteUser({ userName: req.query.userName });
1115
- res.status(200).send(foundAndDeleted ? 'Mock user deleted' : 'Mock user not found');
1116
- }
1117
- else {
1118
- res.status(401).send('Unauthorized');
1119
- }
1120
- });
1121
- router.get('/mockCallLog', async function (req, res) {
1122
- const secretKey = req.query.secretKey;
1123
- if (secretKey === process.env.APP_SERVER_SECRET_KEY) {
1124
- const callLogs = await mock.getCallLog({ sessionIds: req.query.sessionIds });
1125
- res.status(200).send(callLogs);
1126
- }
1127
- else {
1128
- res.status(401).send('Unauthorized');
1129
- }
1130
- });
1131
- router.post('/mockCallLog', async function (req, res) {
1132
- const secretKey = req.query.secretKey;
1133
- if (secretKey === process.env.APP_SERVER_SECRET_KEY) {
1134
- await mock.createCallLog({ sessionId: req.body.sessionId });
1135
- res.status(200).send('Mock call log created');
1136
- }
1137
- else {
1138
- res.status(401).send('Unauthorized');
1139
- }
1140
- });
1141
- router.delete('/mockCallLog', async function (req, res) {
1142
- const secretKey = req.query.secretKey;
1143
- if (secretKey === process.env.APP_SERVER_SECRET_KEY) {
1144
- await mock.cleanUpMockLogs();
1145
- res.status(200).send('Mock call logs cleaned up');
1146
- }
1147
- else {
1148
- res.status(401).send('Unauthorized');
1149
- }
1150
- });
1151
- }
1152
-
1153
- return router;
1154
- }
1155
-
1156
- // Create middleware for core functionality
1157
- function createCoreMiddleware() {
1158
- return [
1159
- bodyParser.json(),
1160
- cors({
1161
- methods: ['GET', 'POST', 'PATCH', 'PUT']
1162
- })
1163
- ];
1164
- }
1165
-
1166
- // Initialize core services
1167
- async function initializeCore(options = {}) {
1168
- const {
1169
- skipDatabaseInit = false,
1170
- skipAnalyticsInit = false,
1171
- } = options;
1172
-
1173
- if (!skipAnalyticsInit) {
1174
- analytics.init();
1175
- }
1176
-
1177
- if (!skipDatabaseInit) {
1178
- await initDB();
1179
- }
1180
- }
1181
-
1182
- // Create a complete app with core functionality
1183
- function createCoreApp(options = {}) {
1184
- initializeCore(options);
1185
- const app = express();
1186
-
1187
- // Apply core middleware
1188
- const coreMiddleware = createCoreMiddleware();
1189
- coreMiddleware.forEach(middleware => app.use(middleware));
1190
-
1191
- // Apply core routes
1192
- const coreRouter = createCoreRouter();
1193
- app.use('/', coreRouter);
1194
-
1195
- return app;
1196
- }
1197
-
1198
- exports.createCoreRouter = createCoreRouter;
1199
- exports.createCoreMiddleware = createCoreMiddleware;
1200
- exports.createCoreApp = createCoreApp;
1201
- exports.initializeCore = initializeCore;
1202
- exports.adapterRegistry = adapterRegistry;
1
+ const express = require('express');
2
+ const cors = require('cors')
3
+ const bodyParser = require('body-parser');
4
+ const dynamoose = require('dynamoose');
5
+ const axios = require('axios');
6
+ const { UserModel } = require('./models/userModel');
7
+ const { CallLogModel } = require('./models/callLogModel');
8
+ const { MessageLogModel } = require('./models/messageLogModel');
9
+ const { AdminConfigModel } = require('./models/adminConfigModel');
10
+ const { CacheModel } = require('./models/cacheModel');
11
+ const jwt = require('./lib/jwt');
12
+ const logCore = require('./handlers/log');
13
+ const contactCore = require('./handlers/contact');
14
+ const authCore = require('./handlers/auth');
15
+ const adminCore = require('./handlers/admin');
16
+ const userCore = require('./handlers/user');
17
+ const dispositionCore = require('./handlers/disposition');
18
+ const mock = require('./adapter/mock');
19
+ const releaseNotes = require('./releaseNotes.json');
20
+ const analytics = require('./lib/analytics');
21
+ const util = require('./lib/util');
22
+ const adapterRegistry = require('./adapter/registry');
23
+
24
+ let packageJson = null;
25
+ try {
26
+ packageJson = require('./package.json');
27
+ }
28
+ catch (e) {
29
+ packageJson = require('../package.json');
30
+ }
31
+
32
+ // For using dynamodb in local env
33
+ if (process.env.DYNAMODB_LOCALHOST) {
34
+ dynamoose.aws.ddb.local(process.env.DYNAMODB_LOCALHOST);
35
+ }
36
+
37
+ axios.defaults.headers.common['Unified-CRM-Extension-Version'] = packageJson.version;
38
+
39
+ async function initDB() {
40
+ if (!process.env.DISABLE_SYNC_DB_TABLE) {
41
+ console.log('creating db tables if not exist...');
42
+ await UserModel.sync();
43
+ await CallLogModel.sync();
44
+ await MessageLogModel.sync();
45
+ await AdminConfigModel.sync();
46
+ await CacheModel.sync();
47
+ }
48
+ }
49
+
50
+ function getAnalyticsVariablesInReqHeaders({ headers }) {
51
+ const hashedExtensionId = headers['rc-extension-id'];
52
+ const hashedAccountId = headers['rc-account-id'];
53
+ const ip = headers['x-forwarded-for']?.split(',')?.find(i => !i.startsWith('10.'));
54
+ const userAgent = headers['user-agent'];
55
+ const author = headers['developer-author-name'];
56
+ const eventAddedVia = headers['eventAddedVia'];
57
+ return {
58
+ hashedAccountId,
59
+ hashedExtensionId,
60
+ ip,
61
+ userAgent,
62
+ author,
63
+ eventAddedVia
64
+ }
65
+ }
66
+
67
+ // Create a router with all core routes
68
+ function createCoreRouter() {
69
+ const router = express.Router();
70
+
71
+ // Move all app.get, app.post, etc. to router.get, router.post, etc.
72
+ router.get('/releaseNotes', async function (req, res) {
73
+ const globalReleaseNotes = releaseNotes;
74
+ const adapterReleaseNotes = adapterRegistry.getReleaseNotes();
75
+ const mergedReleaseNotes = {};
76
+ const versions = Object.keys(adapterReleaseNotes);
77
+ for (const version of versions) {
78
+ mergedReleaseNotes[version] = {
79
+ global: globalReleaseNotes[version]?.global ?? {},
80
+ ...adapterReleaseNotes[version] ?? {}
81
+ };
82
+ }
83
+ res.json(mergedReleaseNotes);
84
+ });
85
+
86
+ router.get('/crmManifest', (req, res) => {
87
+ try {
88
+ const platformName = req.query.platformName || 'default';
89
+ const crmManifest = adapterRegistry.getManifest(platformName);
90
+ if (crmManifest) {
91
+ // Override app server url for local development
92
+ if (process.env.OVERRIDE_APP_SERVER) {
93
+ crmManifest.serverUrl = process.env.OVERRIDE_APP_SERVER;
94
+ }
95
+ // Override server side logging server url for local development
96
+ if (process.env.OVERRIDE_SERVER_SIDE_LOGGING_SERVER && crmManifest.platforms) {
97
+ Object.keys(crmManifest.platforms).forEach(platformName => {
98
+ const platform = crmManifest.platforms[platformName];
99
+ if (platform.serverSideLogging) {
100
+ platform.serverSideLogging.url = process.env.OVERRIDE_SERVER_SIDE_LOGGING_SERVER;
101
+ }
102
+ });
103
+ }
104
+ if (!crmManifest.author?.name) {
105
+ throw 'author name is required';
106
+ }
107
+ res.json(crmManifest);
108
+ }
109
+ else {
110
+ res.status(400).send('Platform not found');
111
+ }
112
+ }
113
+ catch (e) {
114
+ res.status(400).send('Platform not found');
115
+ }
116
+ });
117
+
118
+ router.get('/isAlive', (req, res) => {
119
+ res.send(`OK`);
120
+ });
121
+
122
+ router.get('/licenseStatus', async (req, res) => {
123
+ const requestStartTime = new Date().getTime();
124
+ let platformName = null;
125
+ let success = false;
126
+ let extraData = {};
127
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
128
+ try {
129
+ const jwtToken = req.query.jwtToken;
130
+ if (jwtToken) {
131
+ const { id: userId, platform } = jwt.decodeJwt(jwtToken);
132
+ platformName = platform;
133
+ if (!userId) {
134
+ res.status(400).send();
135
+ success = true;
136
+ }
137
+ const licenseStatus = await authCore.getLicenseStatus({ userId, platform });
138
+ res.status(200).send(licenseStatus);
139
+ success = true;
140
+ }
141
+ else {
142
+ res.status(200).send({
143
+ isLicenseValid: false,
144
+ licenseStatus: 'Invalid (Invalid user session)',
145
+ licenseStatusDescription: ''
146
+ });
147
+ success = true;
148
+ }
149
+ }
150
+ catch (e) {
151
+ res.status(200).send({
152
+ isLicenseValid: false,
153
+ licenseStatus: 'Invalid (Connect to get license status)',
154
+ licenseStatusDescription: ''
155
+ });
156
+ success = false;
157
+ }
158
+ const requestEndTime = new Date().getTime();
159
+ analytics.track({
160
+ eventName: 'Check license status',
161
+ interfaceName: 'checkLicenseStatus',
162
+ adapterName: platformName,
163
+ accountId: hashedAccountId,
164
+ extensionId: hashedExtensionId,
165
+ success,
166
+ requestDuration: (requestEndTime - requestStartTime) / 1000,
167
+ userAgent,
168
+ ip,
169
+ author,
170
+ extras: {
171
+ ...extraData
172
+ },
173
+ eventAddedVia
174
+ });
175
+ });
176
+
177
+ router.get('/authValidation', async (req, res) => {
178
+ const requestStartTime = new Date().getTime();
179
+ let platformName = null;
180
+ let success = false;
181
+ let validationPass = false;
182
+ let reason = '';
183
+ let statusCode = 200;
184
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
185
+ try {
186
+ const jwtToken = req.query.jwtToken;
187
+ if (jwtToken) {
188
+ const decodedToken = jwt.decodeJwt(jwtToken);
189
+ if (!decodedToken) {
190
+ res.status(400).send('Invalid JWT token');
191
+ return;
192
+ }
193
+ const { id: userId, platform } = decodedToken;
194
+ platformName = platform;
195
+ const { successful, returnMessage, failReason, status } = await authCore.authValidation({ platform, userId });
196
+ success = true;
197
+ validationPass = successful;
198
+ reason = failReason;
199
+ statusCode = status;
200
+ res.status(200).send({ successful, returnMessage });
201
+ }
202
+ else {
203
+ res.status(400).send('Please go to Settings and authorize CRM platform');
204
+ success = false;
205
+ }
206
+ }
207
+ catch (e) {
208
+ console.log(`platform: ${platformName} \n${e.stack}`);
209
+ statusCode = e.response?.status ?? 'unknown';
210
+ res.status(400).send(e);
211
+ success = false;
212
+ }
213
+ const requestEndTime = new Date().getTime();
214
+ analytics.track({
215
+ eventName: 'Auth validation',
216
+ interfaceName: 'authValidation',
217
+ adapterName: platformName,
218
+ accountId: hashedAccountId,
219
+ extensionId: hashedExtensionId,
220
+ success,
221
+ requestDuration: (requestEndTime - requestStartTime) / 1000,
222
+ userAgent,
223
+ ip,
224
+ author,
225
+ extras: {
226
+ validationPass,
227
+ reason,
228
+ statusCode
229
+ },
230
+ eventAddedVia
231
+ });
232
+ });
233
+
234
+ router.get('/serverVersionInfo', (req, res) => {
235
+ const defaultCrmManifest = adapterRegistry.getManifest('default');
236
+ res.send({ version: defaultCrmManifest?.version ?? 'unknown' });
237
+ });
238
+
239
+ router.post('/admin/settings', async function (req, res) {
240
+ const requestStartTime = new Date().getTime();
241
+ let success = false;
242
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
243
+ try {
244
+ const { isValidated, rcAccountId } = await adminCore.validateAdminRole({ rcAccessToken: req.query.rcAccessToken });
245
+ const hashedRcAccountId = util.getHashValue(rcAccountId, process.env.HASH_KEY);
246
+ if (isValidated) {
247
+ await adminCore.upsertAdminSettings({ hashedRcAccountId, adminSettings: req.body.adminSettings });
248
+ res.status(200).send('Admin settings updated');
249
+ success = true;
250
+ }
251
+ else {
252
+ res.status(401).send('Admin validation failed');
253
+ success = false;
254
+ }
255
+ }
256
+ catch (e) {
257
+ console.log(`${e.stack}`);
258
+ res.status(400).send(e);
259
+ }
260
+ const requestEndTime = new Date().getTime();
261
+ analytics.track({
262
+ eventName: 'Set admin settings',
263
+ interfaceName: 'setAdminSettings',
264
+ accountId: hashedAccountId,
265
+ extensionId: hashedExtensionId,
266
+ success,
267
+ requestDuration: (requestEndTime - requestStartTime) / 1000,
268
+ userAgent,
269
+ ip,
270
+ author,
271
+ eventAddedVia
272
+ });
273
+ });
274
+
275
+ router.get('/admin/settings', async function (req, res) {
276
+ const requestStartTime = new Date().getTime();
277
+ let platformName = null;
278
+ let success = false;
279
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
280
+ try {
281
+ const jwtToken = req.query.jwtToken;
282
+ if (jwtToken) {
283
+ const unAuthData = jwt.decodeJwt(jwtToken);
284
+ platformName = unAuthData?.platform ?? 'Unknown';
285
+ const user = await UserModel.findByPk(unAuthData?.id);
286
+ if (!user) {
287
+ res.status(400).send('User not found');
288
+ return;
289
+ }
290
+ const { isValidated, rcAccountId } = await adminCore.validateAdminRole({ rcAccessToken: req.query.rcAccessToken });
291
+ const hashedRcAccountId = util.getHashValue(rcAccountId, process.env.HASH_KEY);
292
+ if (isValidated) {
293
+ const adminSettings = await adminCore.getAdminSettings({ hashedRcAccountId });
294
+ if (adminSettings) {
295
+ res.status(200).send(adminSettings);
296
+ }
297
+ else {
298
+ res.status(200).send({
299
+ customAdapter: null,
300
+ userSettings: {}
301
+ });
302
+ }
303
+ success = true;
304
+ }
305
+ else {
306
+ res.status(401).send('Admin validation failed');
307
+ success = true;
308
+ }
309
+ }
310
+ else {
311
+ res.status(400).send('Please go to Settings and authorize CRM platform');
312
+ success = false;
313
+ }
314
+ }
315
+ catch (e) {
316
+ res.status(400).send(e);
317
+ }
318
+ const requestEndTime = new Date().getTime();
319
+ analytics.track({
320
+ eventName: 'Get admin settings',
321
+ interfaceName: 'getAdminSettings',
322
+ adapterName: platformName,
323
+ accountId: hashedAccountId,
324
+ extensionId: hashedExtensionId,
325
+ success,
326
+ requestDuration: (requestEndTime - requestStartTime) / 1000,
327
+ userAgent,
328
+ ip,
329
+ author,
330
+ eventAddedVia
331
+ });
332
+ });
333
+
334
+ router.get('/admin/serverLoggingSettings', async function (req, res) {
335
+ const requestStartTime = new Date().getTime();
336
+ let platformName = null;
337
+ let success = false;
338
+ const jwtToken = req.query.jwtToken;
339
+ if (!jwtToken) {
340
+ res.status(400).send('Please go to Settings and authorize CRM platform');
341
+ return;
342
+ }
343
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
344
+ try {
345
+ const unAuthData = jwt.decodeJwt(jwtToken);
346
+ if (!unAuthData?.id) {
347
+ res.status(400).send('Please go to Settings and authorize CRM platform');
348
+ return;
349
+ }
350
+ platformName = unAuthData?.platform ?? 'Unknown';
351
+ const user = await UserModel.findByPk(unAuthData?.id);
352
+ if (!user) {
353
+ res.status(400).send('User not found');
354
+ return;
355
+ }
356
+ const serverLoggingSettings = await adminCore.getServerLoggingSettings({ user });
357
+ res.status(200).send(serverLoggingSettings);
358
+ success = true;
359
+ }
360
+ catch (e) {
361
+ console.log(`${e.stack}`);
362
+ res.status(400).send(e);
363
+ }
364
+ const requestEndTime = new Date().getTime();
365
+ analytics.track({
366
+ eventName: 'Get server logging settings',
367
+ interfaceName: 'getServerLoggingSettings',
368
+ adapterName: platformName,
369
+ accountId: hashedAccountId,
370
+ extensionId: hashedExtensionId,
371
+ success,
372
+ requestDuration: (requestEndTime - requestStartTime) / 1000,
373
+ userAgent,
374
+ ip,
375
+ author,
376
+ eventAddedVia
377
+ });
378
+ });
379
+
380
+ router.post('/admin/serverLoggingSettings', async function (req, res) {
381
+ const requestStartTime = new Date().getTime();
382
+ let platformName = null;
383
+ let success = false;
384
+ const jwtToken = req.query.jwtToken;
385
+ if (!jwtToken) {
386
+ res.status(400).send('Please go to Settings and authorize CRM platform');
387
+ return;
388
+ }
389
+ if (!req.body.additionalFieldValues) {
390
+ res.status(400).send('Missing additionalFieldValues');
391
+ return;
392
+ }
393
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
394
+ try {
395
+ const unAuthData = jwt.decodeJwt(jwtToken);
396
+ if (!unAuthData?.id) {
397
+ res.status(400).send('Please go to Settings and authorize CRM platform');
398
+ return;
399
+ }
400
+ platformName = unAuthData?.platform ?? 'Unknown';
401
+ const user = await UserModel.findByPk(unAuthData?.id);
402
+ if (!user) {
403
+ res.status(400).send('User not found');
404
+ return;
405
+ }
406
+ const { successful, returnMessage } = await adminCore.updateServerLoggingSettings({ user, additionalFieldValues: req.body.additionalFieldValues });
407
+ res.status(200).send({ successful, returnMessage });
408
+ success = true;
409
+ }
410
+ catch (e) {
411
+ console.log(`${e.stack}`);
412
+ res.status(400).send({ successful: false, returnMessage: { messageType: 'warning', message: 'Server logging settings update failed', ttl: 5000 } });
413
+ success = false;
414
+ }
415
+ const requestEndTime = new Date().getTime();
416
+ analytics.track({
417
+ eventName: 'Set server logging settings',
418
+ interfaceName: 'setServerLoggingSettings',
419
+ adapterName: platformName,
420
+ accountId: hashedAccountId,
421
+ extensionId: hashedExtensionId,
422
+ success,
423
+ requestDuration: (requestEndTime - requestStartTime) / 1000,
424
+ userAgent,
425
+ ip,
426
+ author,
427
+ eventAddedVia
428
+ });
429
+ })
430
+
431
+ router.get('/user/preloadSettings', async function (req, res) {
432
+ try {
433
+ const rcAccessToken = req.query.rcAccessToken;
434
+ const rcAccountId = req.query.rcAccountId;
435
+ if (rcAccessToken || rcAccountId) {
436
+ const userSettings = await userCore.getUserSettingsByAdmin({ rcAccessToken, rcAccountId });
437
+ res.status(200).send(userSettings);
438
+ }
439
+ else {
440
+ res.status(400).send('Cannot find rc user login');
441
+ }
442
+ }
443
+ catch (e) {
444
+ console.log(`${e.stack}`);
445
+ res.status(400).send(e);
446
+ }
447
+ }
448
+ );
449
+ router.get('/user/settings', async function (req, res) {
450
+ const requestStartTime = new Date().getTime();
451
+ let platformName = null;
452
+ let success = false;
453
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
454
+ try {
455
+ const jwtToken = req.query.jwtToken;
456
+ if (jwtToken) {
457
+ const unAuthData = jwt.decodeJwt(jwtToken);
458
+ platformName = unAuthData?.platform ?? 'Unknown';
459
+ const user = await UserModel.findByPk(unAuthData?.id);
460
+ if (!user) {
461
+ res.status(400).send('User not found');
462
+ return;
463
+ }
464
+ else {
465
+ const rcAccessToken = req.query.rcAccessToken;
466
+ const rcAccountId = req.query.rcAccountId;
467
+ const userSettings = await userCore.getUserSettings({ user, rcAccessToken, rcAccountId });
468
+ success = true;
469
+ res.status(200).send(userSettings);
470
+ }
471
+ }
472
+ else {
473
+ success = false;
474
+ res.status(400).send('Please go to Settings and authorize CRM platform');
475
+ }
476
+ }
477
+ catch (e) {
478
+ console.log(`platform: ${platformName} \n${e.stack}`);
479
+ }
480
+ const requestEndTime = new Date().getTime();
481
+ analytics.track({
482
+ eventName: 'Get user settings',
483
+ interfaceName: 'getUserSettings',
484
+ adapterName: platformName,
485
+ accountId: hashedAccountId,
486
+ extensionId: hashedExtensionId,
487
+ success,
488
+ requestDuration: (requestEndTime - requestStartTime) / 1000,
489
+ userAgent,
490
+ ip,
491
+ author,
492
+ eventAddedVia
493
+ });
494
+ });
495
+
496
+ router.post('/user/settings', async function (req, res) {
497
+ const requestStartTime = new Date().getTime();
498
+ let platformName = null;
499
+ let success = false;
500
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
501
+ try {
502
+ const jwtToken = req.query.jwtToken;
503
+ if (jwtToken) {
504
+ const unAuthData = jwt.decodeJwt(jwtToken);
505
+ platformName = unAuthData?.platform;
506
+ if (!platformName) {
507
+ res.status(400).send('Unknown platform');
508
+ }
509
+ const user = await UserModel.findByPk(unAuthData?.id);
510
+ if (!user) {
511
+ res.status(400).send();
512
+ }
513
+ const { userSettings } = await userCore.updateUserSettings({ user, userSettings: req.body.userSettings, platformName });
514
+ res.status(200).send({ userSettings });
515
+ success = true;
516
+ }
517
+ else {
518
+ res.status(400).send('Please go to Settings and authorize CRM platform');
519
+ success = false;
520
+ }
521
+ }
522
+ catch (e) {
523
+ console.log(`platform: ${platformName} \n${e.stack}`);
524
+ }
525
+ const requestEndTime = new Date().getTime();
526
+ analytics.track({
527
+ eventName: 'Set user settings',
528
+ interfaceName: 'setUserSettings',
529
+ adapterName: platformName,
530
+ accountId: hashedAccountId,
531
+ extensionId: hashedExtensionId,
532
+ success,
533
+ requestDuration: (requestEndTime - requestStartTime) / 1000,
534
+ userAgent,
535
+ ip,
536
+ author,
537
+ eventAddedVia
538
+ });
539
+ });
540
+
541
+ router.get('/hostname', async function (req, res) {
542
+ try {
543
+ const jwtToken = req.query.jwtToken;
544
+ if (jwtToken) {
545
+ const unAuthData = jwt.decodeJwt(jwtToken);
546
+ const user = await UserModel.findByPk(unAuthData?.id);
547
+ if (!user) {
548
+ res.status(400).send();
549
+ return;
550
+ }
551
+ res.status(200).send(user.hostname);
552
+ }
553
+ else {
554
+ res.status(400).send('Please go to Settings and authorize CRM platform');
555
+ }
556
+ }
557
+ catch (e) {
558
+ console.log(`${e.stack}`);
559
+ res.status(500).send(e);
560
+ }
561
+ })
562
+
563
+ router.get('/oauth-callback', async function (req, res) {
564
+ const requestStartTime = new Date().getTime();
565
+ let platformName = null;
566
+ let success = false;
567
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
568
+ try {
569
+ if (!req.query?.callbackUri || req.query.callbackUri === 'undefined') {
570
+ throw 'Missing callbackUri';
571
+ }
572
+ platformName = req.query.state ?
573
+ req.query.state.split('platform=')[1] :
574
+ decodeURIComponent(req.originalUrl).split('state=')[1].split('&')[0].split('platform=')[1];
575
+ const hostname = req.query.hostname;
576
+ const tokenUrl = req.query.tokenUrl;
577
+ if (!platformName) {
578
+ throw 'Missing platform name';
579
+ }
580
+ const hasAuthCodeInCallbackUri = req.query.callbackUri.includes('code=');
581
+ if (!hasAuthCodeInCallbackUri) {
582
+ // eslint-disable-next-line no-param-reassign
583
+ req.query.callbackUri = `${req.query.callbackUri}&code=${req.query.code}`;
584
+ }
585
+ const { userInfo, returnMessage } = await authCore.onOAuthCallback({
586
+ platform: platformName,
587
+ hostname,
588
+ tokenUrl,
589
+ callbackUri: req.query.callbackUri,
590
+ apiUrl: req.query.apiUrl,
591
+ username: req.query.username,
592
+ query: req.query
593
+ });
594
+ if (userInfo) {
595
+ const jwtToken = jwt.generateJwt({
596
+ id: userInfo.id.toString(),
597
+ platform: platformName
598
+ });
599
+ res.status(200).send({ jwtToken, name: userInfo.name, returnMessage });
600
+ success = true;
601
+ }
602
+ else {
603
+ res.status(200).send({ returnMessage });
604
+ success = false;
605
+ }
606
+ }
607
+ catch (e) {
608
+ console.log(`platform: ${platformName} \n${e.stack}`);
609
+ res.status(400).send(e);
610
+ success = false;
611
+ }
612
+ const requestEndTime = new Date().getTime();
613
+ analytics.track({
614
+ eventName: 'OAuth Callback',
615
+ interfaceName: 'onOAuthCallback',
616
+ adapterName: platformName,
617
+ accountId: hashedAccountId,
618
+ extensionId: hashedExtensionId,
619
+ success,
620
+ requestDuration: (requestEndTime - requestStartTime) / 1000,
621
+ userAgent,
622
+ ip,
623
+ author,
624
+ eventAddedVia
625
+ });
626
+ })
627
+ router.post('/apiKeyLogin', async function (req, res) {
628
+ const requestStartTime = new Date().getTime();
629
+ let platformName = null;
630
+ let success = false;
631
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
632
+ try {
633
+ const platform = req.body.platform;
634
+ platformName = platform;
635
+ const apiKey = req.body.apiKey;
636
+ const hostname = req.body.hostname;
637
+ const additionalInfo = req.body.additionalInfo;
638
+ if (!platform) {
639
+ throw 'Missing platform name';
640
+ }
641
+ if (!apiKey) {
642
+ throw 'Missing api key';
643
+ }
644
+ const { userInfo, returnMessage } = await authCore.onApiKeyLogin({ platform, hostname, apiKey, additionalInfo });
645
+ if (userInfo) {
646
+ const jwtToken = jwt.generateJwt({
647
+ id: userInfo.id.toString(),
648
+ platform: platform
649
+ });
650
+ res.status(200).send({ jwtToken, name: userInfo.name, returnMessage });
651
+ success = true;
652
+ }
653
+ else {
654
+ res.status(400).send({ returnMessage });
655
+ success = false;
656
+ }
657
+ }
658
+ catch (e) {
659
+ console.log(`platform: ${platformName} \n${e.stack}`);
660
+ res.status(400).send(e);
661
+ success = false;
662
+ }
663
+ const requestEndTime = new Date().getTime();
664
+ analytics.track({
665
+ eventName: 'API Key Login',
666
+ interfaceName: 'onApiKeyLogin',
667
+ adapterName: platformName,
668
+ accountId: hashedAccountId,
669
+ extensionId: hashedExtensionId,
670
+ success,
671
+ requestDuration: (requestEndTime - requestStartTime) / 1000,
672
+ userAgent,
673
+ ip,
674
+ author,
675
+ eventAddedVia
676
+ });
677
+ })
678
+ router.post('/unAuthorize', async function (req, res) {
679
+ const requestStartTime = new Date().getTime();
680
+ let platformName = null;
681
+ let success = false;
682
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
683
+ try {
684
+ const jwtToken = req.query.jwtToken;
685
+ if (jwtToken) {
686
+ const unAuthData = jwt.decodeJwt(jwtToken);
687
+ platformName = unAuthData?.platform ?? 'Unknown';
688
+ const userToLogout = await UserModel.findByPk(unAuthData?.id);
689
+ if (!userToLogout) {
690
+ res.status(400).send();
691
+ return;
692
+ }
693
+ const platformModule = adapterRegistry.getAdapter(unAuthData?.platform ?? 'Unknown');
694
+ const { returnMessage } = await platformModule.unAuthorize({ user: userToLogout });
695
+ res.status(200).send({ returnMessage });
696
+ success = true;
697
+ }
698
+ else {
699
+ res.status(400).send('Please go to Settings and authorize CRM platform');
700
+ success = false;
701
+ }
702
+ }
703
+ catch (e) {
704
+ console.log(`platform: ${platformName} \n${e.stack}`);
705
+ res.status(400).send(e);
706
+ success = false;
707
+ }
708
+ const requestEndTime = new Date().getTime();
709
+ analytics.track({
710
+ eventName: 'Unauthorize',
711
+ interfaceName: 'unAuthorize',
712
+ adapterName: platformName,
713
+ accountId: hashedAccountId,
714
+ extensionId: hashedExtensionId,
715
+ success,
716
+ requestDuration: (requestEndTime - requestStartTime) / 1000,
717
+ userAgent,
718
+ ip,
719
+ author,
720
+ eventAddedVia
721
+ });
722
+ });
723
+ router.get('/userInfoHash', async function (req, res) {
724
+ try {
725
+ const extensionId = util.getHashValue(req.query.extensionId, process.env.HASH_KEY);
726
+ const accountId = util.getHashValue(req.query.accountId, process.env.HASH_KEY);
727
+ res.status(200).send({ extensionId, accountId });
728
+ }
729
+ catch (e) {
730
+ console.log(`${e.stack}`);
731
+ res.status(400).send(e);
732
+ }
733
+ })
734
+ router.get('/contact', async function (req, res) {
735
+ const requestStartTime = new Date().getTime();
736
+ let platformName = null;
737
+ let success = false;
738
+ let resultCount = 0;
739
+ let extraData = {};
740
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
741
+ try {
742
+ const jwtToken = req.query.jwtToken;
743
+ if (jwtToken) {
744
+ const decodedToken = jwt.decodeJwt(jwtToken);
745
+ if (!decodedToken) {
746
+ res.status(400).send('Please go to Settings and authorize CRM platform');
747
+ return;
748
+ }
749
+ const { id: userId, platform } = decodedToken;
750
+ platformName = platform;
751
+ const { successful, returnMessage, contact, extraDataTracking } = await contactCore.findContact({ platform, userId, phoneNumber: req.query.phoneNumber.replace(' ', '+'), overridingFormat: req.query.overridingFormat, isExtension: req.query?.isExtension ?? false });
752
+ res.status(200).send({ successful, returnMessage, contact });
753
+ if (successful) {
754
+ const nonNewContact = contact?.filter(c => !c.isNewContact) ?? [];
755
+ resultCount = nonNewContact.length;
756
+ }
757
+ success = successful;
758
+ if (extraDataTracking) {
759
+ extraData = extraDataTracking;
760
+ }
761
+ }
762
+ else {
763
+ res.status(400).send('Please go to Settings and authorize CRM platform');
764
+ success = false;
765
+ }
766
+ }
767
+ catch (e) {
768
+ console.log(`platform: ${platformName} \n${e.stack}`);
769
+ extraData.statusCode = e.response?.status ?? 'unknown';
770
+ res.status(400).send(e);
771
+ success = false;
772
+ }
773
+ const requestEndTime = new Date().getTime();
774
+ analytics.track({
775
+ eventName: 'Find contact',
776
+ interfaceName: 'findContact',
777
+ adapterName: platformName,
778
+ accountId: hashedAccountId,
779
+ extensionId: hashedExtensionId,
780
+ success,
781
+ requestDuration: (requestEndTime - requestStartTime) / 1000,
782
+ userAgent,
783
+ ip,
784
+ author,
785
+ extras: {
786
+ resultCount,
787
+ ...extraData
788
+ },
789
+ eventAddedVia
790
+ });
791
+ });
792
+ router.post('/contact', async function (req, res) {
793
+ const requestStartTime = new Date().getTime();
794
+ let platformName = null;
795
+ let success = false;
796
+ let extraData = {};
797
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
798
+ try {
799
+ const jwtToken = req.query.jwtToken;
800
+ if (jwtToken) {
801
+ const decodedToken = jwt.decodeJwt(jwtToken);
802
+ if (!decodedToken) {
803
+ res.status(400).send('Please go to Settings and authorize CRM platform');
804
+ return;
805
+ }
806
+ const { id: userId, platform } = decodedToken;
807
+ platformName = platform;
808
+ const { successful, returnMessage, contact, extraDataTracking } = await contactCore.createContact({ platform, userId, phoneNumber: req.body.phoneNumber, newContactName: req.body.newContactName, newContactType: req.body.newContactType, additionalSubmission: req.body.additionalSubmission });
809
+ res.status(200).send({ successful, returnMessage, contact });
810
+ success = true;
811
+ if (extraDataTracking) {
812
+ extraData = extraDataTracking;
813
+ }
814
+ }
815
+ else {
816
+ res.status(400).send('Please go to Settings and authorize CRM platform');
817
+ success = false;
818
+ }
819
+ }
820
+ catch (e) {
821
+ console.log(`platform: ${platformName} \n${e.stack}`);
822
+ extraData.statusCode = e.response?.status ?? 'unknown';
823
+ res.status(400).send(e);
824
+ success = false;
825
+ }
826
+ const requestEndTime = new Date().getTime();
827
+ analytics.track({
828
+ eventName: 'Create contact',
829
+ interfaceName: 'createContact',
830
+ adapterName: platformName,
831
+ accountId: hashedAccountId,
832
+ extensionId: hashedExtensionId,
833
+ success,
834
+ requestDuration: (requestEndTime - requestStartTime) / 1000,
835
+ userAgent,
836
+ ip,
837
+ author,
838
+ extras: {
839
+ ...extraData
840
+ },
841
+ eventAddedVia
842
+ });
843
+ });
844
+ router.post('/callLog/cacheNote', async function (req, res) {
845
+ const requestStartTime = new Date().getTime();
846
+ let platformName = null;
847
+ let success = false;
848
+ let extraData = {};
849
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
850
+ try {
851
+ const jwtToken = req.query.jwtToken;
852
+ if (jwtToken) {
853
+ const decodedToken = jwt.decodeJwt(jwtToken);
854
+ if (!decodedToken) {
855
+ res.status(400).send('Please go to Settings and authorize CRM platform');
856
+ return;
857
+ }
858
+ const { id: userId, platform } = decodedToken;
859
+ platformName = platform;
860
+ const { successful, returnMessage, extraDataTracking } = await logCore.saveNoteCache({ sessionId: req.body.sessionId, note: req.body.note });
861
+ res.status(200).send({ successful, returnMessage });
862
+ success = true;
863
+ if (extraDataTracking) {
864
+ extraData = extraDataTracking;
865
+ }
866
+ }
867
+ } catch (e) {
868
+ console.log(`platform: ${platformName} \n${e.stack}`);
869
+ extraData.statusCode = e.response?.status ?? 'unknown';
870
+ res.status(400).send(e);
871
+ success = false;
872
+ }
873
+ const requestEndTime = new Date().getTime();
874
+ analytics.track({
875
+ eventName: 'Save note cache',
876
+ interfaceName: 'saveNoteCache',
877
+ adapterName: platformName,
878
+ accountId: hashedAccountId,
879
+ extensionId: hashedExtensionId,
880
+ success,
881
+ });
882
+ })
883
+ router.get('/callLog', async function (req, res) {
884
+ const requestStartTime = new Date().getTime();
885
+ let platformName = null;
886
+ let success = false;
887
+ let extraData = {};
888
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
889
+ try {
890
+ const jwtToken = req.query.jwtToken;
891
+ if (jwtToken) {
892
+ const decodedToken = jwt.decodeJwt(jwtToken);
893
+ if (!decodedToken) {
894
+ res.status(400).send('Please go to Settings and authorize CRM platform');
895
+ return;
896
+ }
897
+ const { id: userId, platform } = decodedToken;
898
+ platformName = platform;
899
+ const { successful, logs, returnMessage, extraDataTracking } = await logCore.getCallLog({ userId, sessionIds: req.query.sessionIds, platform, requireDetails: req.query.requireDetails === 'true' });
900
+ res.status(200).send({ successful, logs, returnMessage });
901
+ success = true;
902
+ if (extraDataTracking) {
903
+ extraData = extraDataTracking;
904
+ }
905
+ }
906
+ else {
907
+ res.status(400).send('Please go to Settings and authorize CRM platform');
908
+ success = false;
909
+ }
910
+ }
911
+ catch (e) {
912
+ console.log(`platform: ${platformName} \n${e.stack}`);
913
+ extraData.statusCode = e.response?.status ?? 'unknown';
914
+ res.status(400).send(e);
915
+ success = false;
916
+ }
917
+ const requestEndTime = new Date().getTime();
918
+ analytics.track({
919
+ eventName: 'Get call log',
920
+ interfaceName: 'getCallLog',
921
+ adapterName: platformName,
922
+ accountId: hashedAccountId,
923
+ extensionId: hashedExtensionId,
924
+ success,
925
+ requestDuration: (requestEndTime - requestStartTime) / 1000,
926
+ userAgent,
927
+ ip,
928
+ author,
929
+ extras: {
930
+ ...extraData
931
+ },
932
+ eventAddedVia
933
+ });
934
+ });
935
+ router.post('/callLog', async function (req, res) {
936
+ const requestStartTime = new Date().getTime();
937
+ let platformName = null;
938
+ let success = false;
939
+ let extraData = {};
940
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
941
+ try {
942
+ const jwtToken = req.query.jwtToken;
943
+ if (jwtToken) {
944
+ const decodedToken = jwt.decodeJwt(jwtToken);
945
+ if (!decodedToken) {
946
+ res.status(400).send('Please go to Settings and authorize CRM platform');
947
+ return;
948
+ }
949
+ const { id: userId, platform } = decodedToken;
950
+ platformName = platform;
951
+ const { successful, logId, returnMessage, extraDataTracking } = await logCore.createCallLog({ platform, userId, incomingData: req.body, isFromSSCL: userAgent === 'SSCL' });
952
+ if (extraDataTracking) {
953
+ extraData = extraDataTracking;
954
+ }
955
+ res.status(200).send({ successful, logId, returnMessage });
956
+ success = true;
957
+ }
958
+ else {
959
+ res.status(400).send('Please go to Settings and authorize CRM platform');
960
+ success = false;
961
+ }
962
+ }
963
+ catch (e) {
964
+ console.log(`platform: ${platformName} \n${e.stack}`);
965
+ extraData.statusCode = e.response?.status ?? 'unknown';
966
+ res.status(400).send(e);
967
+ success = false;
968
+ }
969
+ const requestEndTime = new Date().getTime();
970
+ analytics.track({
971
+ eventName: 'Create call log',
972
+ interfaceName: 'createCallLog',
973
+ adapterName: platformName,
974
+ accountId: hashedAccountId,
975
+ extensionId: hashedExtensionId,
976
+ success,
977
+ requestDuration: (requestEndTime - requestStartTime) / 1000,
978
+ userAgent,
979
+ ip,
980
+ author,
981
+ extras: {
982
+ ...extraData
983
+ },
984
+ eventAddedVia
985
+ });
986
+ });
987
+ router.patch('/callLog', async function (req, res) {
988
+ const requestStartTime = new Date().getTime();
989
+ let platformName = null;
990
+ let success = false;
991
+ let extraData = {};
992
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
993
+ try {
994
+ const jwtToken = req.query.jwtToken;
995
+ if (jwtToken) {
996
+ const decodedToken = jwt.decodeJwt(jwtToken);
997
+ if (!decodedToken) {
998
+ res.status(400).send('Please go to Settings and authorize CRM platform');
999
+ return;
1000
+ }
1001
+ const { id: userId, platform } = decodedToken;
1002
+ platformName = platform;
1003
+ const { successful, logId, updatedNote, returnMessage, extraDataTracking } = await logCore.updateCallLog({ platform, userId, incomingData: req.body, isFromSSCL: userAgent === 'SSCL' });
1004
+ if (extraDataTracking) {
1005
+ extraData = extraDataTracking;
1006
+ }
1007
+ res.status(200).send({ successful, logId, updatedNote, returnMessage });
1008
+ success = true;
1009
+ }
1010
+ else {
1011
+ res.status(400).send('Please go to Settings and authorize CRM platform');
1012
+ success = false;
1013
+ }
1014
+ }
1015
+ catch (e) {
1016
+ console.log(`platform: ${platformName} \n${e.stack}`);
1017
+ extraData.statusCode = e.response?.status ?? 'unknown';
1018
+ res.status(400).send(e);
1019
+ success = false;
1020
+ }
1021
+ const requestEndTime = new Date().getTime();
1022
+ analytics.track({
1023
+ eventName: 'Update call log',
1024
+ interfaceName: 'updateCallLog',
1025
+ adapterName: platformName,
1026
+ accountId: hashedAccountId,
1027
+ extensionId: hashedExtensionId,
1028
+ success,
1029
+ requestDuration: (requestEndTime - requestStartTime) / 1000,
1030
+ userAgent,
1031
+ ip,
1032
+ author,
1033
+ extras: {
1034
+ ...extraData
1035
+ },
1036
+ eventAddedVia
1037
+ });
1038
+ });
1039
+ router.put('/callDisposition', async function (req, res) {
1040
+ const requestStartTime = new Date().getTime();
1041
+ let platformName = null;
1042
+ let success = false;
1043
+ let extraData = {};
1044
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
1045
+ try {
1046
+ const jwtToken = req.query.jwtToken;
1047
+ if (jwtToken) {
1048
+ const { id: userId, platform } = jwt.decodeJwt(jwtToken);
1049
+ platformName = platform;
1050
+ if (!userId) {
1051
+ res.status(400).send();
1052
+ }
1053
+ const { successful, returnMessage, extraDataTracking } = await dispositionCore.upsertCallDisposition({
1054
+ platform,
1055
+ userId,
1056
+ sessionId: req.body.sessionId,
1057
+ dispositions: req.body.dispositions,
1058
+ additionalSubmission: req.body.additionalSubmission
1059
+ });
1060
+ if (extraDataTracking) {
1061
+ extraData = extraDataTracking;
1062
+ }
1063
+ res.status(200).send({ successful, returnMessage });
1064
+ success = true;
1065
+ }
1066
+ else {
1067
+ res.status(400).send('Please go to Settings and authorize CRM platform');
1068
+ success = false;
1069
+ }
1070
+ }
1071
+ catch (e) {
1072
+ console.log(`platform: ${platformName} \n${e.stack}`);
1073
+ extraData.statusCode = e.response?.status ?? 'unknown';
1074
+ res.status(400).send(e);
1075
+ success = false;
1076
+ }
1077
+ const requestEndTime = new Date().getTime();
1078
+ analytics.track({
1079
+ eventName: 'Create call log',
1080
+ interfaceName: 'createCallLog',
1081
+ adapterName: platformName,
1082
+ accountId: hashedAccountId,
1083
+ extensionId: hashedExtensionId,
1084
+ success,
1085
+ requestDuration: (requestEndTime - requestStartTime) / 1000,
1086
+ userAgent,
1087
+ ip,
1088
+ author,
1089
+ extras: {
1090
+ ...extraData
1091
+ },
1092
+ eventAddedVia
1093
+ });
1094
+ });
1095
+ router.post('/messageLog', async function (req, res) {
1096
+ const requestStartTime = new Date().getTime();
1097
+ let platformName = null;
1098
+ let success = false;
1099
+ let statusCode = 200;
1100
+ let extraData = {};
1101
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
1102
+ try {
1103
+ const jwtToken = req.query.jwtToken;
1104
+ if (jwtToken) {
1105
+ const decodedToken = jwt.decodeJwt(jwtToken);
1106
+ if (!decodedToken) {
1107
+ res.status(400).send('Please go to Settings and authorize CRM platform');
1108
+ return;
1109
+ }
1110
+ const { id: userId, platform } = decodedToken;
1111
+ platformName = platform;
1112
+ const { successful, returnMessage, logIds, extraDataTracking } = await logCore.createMessageLog({ platform, userId, incomingData: req.body });
1113
+ if (extraDataTracking) {
1114
+ extraData = extraDataTracking;
1115
+ }
1116
+ res.status(200).send({ successful, returnMessage, logIds });
1117
+ success = true;
1118
+ }
1119
+ else {
1120
+ res.status(400).send('Please go to Settings and authorize CRM platform');
1121
+ success = false;
1122
+ }
1123
+ }
1124
+ catch (e) {
1125
+ console.log(`platform: ${platformName} \n${e.stack}`);
1126
+ statusCode = e.response?.status ?? 'unknown';
1127
+ res.status(400).send(e);
1128
+ success = false;
1129
+ }
1130
+ const requestEndTime = new Date().getTime();
1131
+ analytics.track({
1132
+ eventName: 'Create message log',
1133
+ interfaceName: 'createMessageLog',
1134
+ adapterName: platformName,
1135
+ accountId: hashedAccountId,
1136
+ extensionId: hashedExtensionId,
1137
+ success,
1138
+ requestDuration: (requestEndTime - requestStartTime) / 1000,
1139
+ userAgent,
1140
+ ip,
1141
+ author,
1142
+ extras: {
1143
+ statusCode,
1144
+ ...extraData
1145
+ },
1146
+ eventAddedVia
1147
+ });
1148
+ });
1149
+
1150
+ router.get('/custom/contact/search', async function (req, res) {
1151
+ const requestStartTime = new Date().getTime();
1152
+ let platformName = null;
1153
+ let success = false;
1154
+ let resultCount = 0;
1155
+ let statusCode = 200;
1156
+ const { hashedExtensionId, hashedAccountId, userAgent, ip, author } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
1157
+ try {
1158
+ const jwtToken = req.query.jwtToken;
1159
+ if (jwtToken) {
1160
+ const { id: userId, platform } = jwt.decodeJwt(jwtToken);
1161
+ platformName = platform;
1162
+ const { successful, returnMessage, contact } = await contactCore.findContactWithName({ platform, userId, name: req.query.name });
1163
+ res.status(200).send({ successful, returnMessage, contact });
1164
+ success = successful;
1165
+ }
1166
+ else {
1167
+ res.status(400).send('Please go to Settings and authorize CRM platform');
1168
+ success = false;
1169
+ }
1170
+
1171
+ }
1172
+ catch (e) {
1173
+ console.log(`platform: ${platformName} \n${e.stack}`);
1174
+ statusCode = e.response?.status ?? 'unknown';
1175
+ res.status(400).send(e);
1176
+ success = false;
1177
+ }
1178
+ const requestEndTime = new Date().getTime();
1179
+ analytics.track({
1180
+ eventName: 'Contact Search by Name',
1181
+ interfaceName: 'contactSearchByName',
1182
+ adapterName: platformName,
1183
+ accountId: hashedAccountId,
1184
+ extensionId: hashedExtensionId,
1185
+ success,
1186
+ requestDuration: (requestEndTime - requestStartTime) / 1000,
1187
+ userAgent,
1188
+ ip,
1189
+ author,
1190
+ extras: {
1191
+ statusCode
1192
+ }
1193
+ });
1194
+
1195
+ });
1196
+ if (process.env.IS_PROD === 'false') {
1197
+ router.post('/registerMockUser', async function (req, res) {
1198
+ const secretKey = req.query.secretKey;
1199
+ if (secretKey === process.env.APP_SERVER_SECRET_KEY) {
1200
+ const mockUser = await mock.createUser({ userName: req.body.userName });
1201
+ res.status(200).send(mockUser ? 'Mock user registered' : 'Mock user already existed');
1202
+ }
1203
+ else {
1204
+ res.status(401).send('Unauthorized');
1205
+ }
1206
+ });
1207
+ router.delete('/deleteMockUser', async function (req, res) {
1208
+ const secretKey = req.query.secretKey;
1209
+ if (secretKey === process.env.APP_SERVER_SECRET_KEY) {
1210
+ const foundAndDeleted = await mock.deleteUser({ userName: req.query.userName });
1211
+ res.status(200).send(foundAndDeleted ? 'Mock user deleted' : 'Mock user not found');
1212
+ }
1213
+ else {
1214
+ res.status(401).send('Unauthorized');
1215
+ }
1216
+ });
1217
+ router.get('/mockCallLog', async function (req, res) {
1218
+ const secretKey = req.query.secretKey;
1219
+ if (secretKey === process.env.APP_SERVER_SECRET_KEY) {
1220
+ const callLogs = await mock.getCallLog({ sessionIds: req.query.sessionIds });
1221
+ res.status(200).send(callLogs);
1222
+ }
1223
+ else {
1224
+ res.status(401).send('Unauthorized');
1225
+ }
1226
+ });
1227
+ router.post('/mockCallLog', async function (req, res) {
1228
+ const secretKey = req.query.secretKey;
1229
+ if (secretKey === process.env.APP_SERVER_SECRET_KEY) {
1230
+ await mock.createCallLog({ sessionId: req.body.sessionId });
1231
+ res.status(200).send('Mock call log created');
1232
+ }
1233
+ else {
1234
+ res.status(401).send('Unauthorized');
1235
+ }
1236
+ });
1237
+ router.delete('/mockCallLog', async function (req, res) {
1238
+ const secretKey = req.query.secretKey;
1239
+ if (secretKey === process.env.APP_SERVER_SECRET_KEY) {
1240
+ await mock.cleanUpMockLogs();
1241
+ res.status(200).send('Mock call logs cleaned up');
1242
+ }
1243
+ else {
1244
+ res.status(401).send('Unauthorized');
1245
+ }
1246
+ });
1247
+ }
1248
+
1249
+ return router;
1250
+ }
1251
+
1252
+ // Create middleware for core functionality
1253
+ function createCoreMiddleware() {
1254
+ return [
1255
+ bodyParser.json(),
1256
+ cors({
1257
+ methods: ['GET', 'POST', 'PATCH', 'PUT']
1258
+ })
1259
+ ];
1260
+ }
1261
+
1262
+ // Initialize core services
1263
+ async function initializeCore(options = {}) {
1264
+ const {
1265
+ skipDatabaseInit = false,
1266
+ skipAnalyticsInit = false,
1267
+ } = options;
1268
+
1269
+ if (!skipAnalyticsInit) {
1270
+ analytics.init();
1271
+ }
1272
+
1273
+ if (!skipDatabaseInit) {
1274
+ await initDB();
1275
+ }
1276
+ }
1277
+
1278
+ // Create a complete app with core functionality
1279
+ function createCoreApp(options = {}) {
1280
+ initializeCore(options);
1281
+ const app = express();
1282
+
1283
+ // Allow bigger POST body size
1284
+ app.use(express.json({ limit: '50mb' }));
1285
+ app.use(express.urlencoded({ limit: '50mb', extended: true }));
1286
+
1287
+ // Apply core middleware
1288
+ const coreMiddleware = createCoreMiddleware();
1289
+ coreMiddleware.forEach(middleware => app.use(middleware));
1290
+
1291
+ // Apply core routes
1292
+ const coreRouter = createCoreRouter();
1293
+ app.use('/', coreRouter);
1294
+
1295
+ return app;
1296
+ }
1297
+
1298
+ exports.createCoreRouter = createCoreRouter;
1299
+ exports.createCoreMiddleware = createCoreMiddleware;
1300
+ exports.createCoreApp = createCoreApp;
1301
+ exports.initializeCore = initializeCore;
1302
+ exports.adapterRegistry = adapterRegistry;