UNPKG

@app-connect/core

Version:
1,205 lines (1,172 loc) 47.6 kB
const express = require('express'); const cors = require('cors') const bodyParser = require('body-parser'); const dynamoose = require('dynamoose'); const axios = require('axios'); const { UserModel } = require('./models/userModel'); const { CallLogModel } = require('./models/callLogModel'); const { MessageLogModel } = require('./models/messageLogModel'); const { AdminConfigModel } = require('./models/adminConfigModel'); const { CacheModel } = require('./models/cacheModel'); const jwt = require('./lib/jwt'); const logCore = require('./handlers/log'); const contactCore = require('./handlers/contact'); const authCore = require('./handlers/auth'); const adminCore = require('./handlers/admin'); const userCore = require('./handlers/user'); const dispositionCore = require('./handlers/disposition'); const mock = require('./adapter/mock'); const releaseNotes = require('./releaseNotes.json'); const analytics = require('./lib/analytics'); const util = require('./lib/util'); const adapterRegistry = require('./adapter/registry'); let packageJson = null; try { packageJson = require('./package.json'); } catch (e) { packageJson = require('../package.json'); } // For using dynamodb in local env if (process.env.DYNAMODB_LOCALHOST) { dynamoose.aws.ddb.local(process.env.DYNAMODB_LOCALHOST); } axios.defaults.headers.common['Unified-CRM-Extension-Version'] = packageJson.version; async function initDB() { if (!process.env.DISABLE_SYNC_DB_TABLE) { console.log('creating db tables if not exist...'); await UserModel.sync(); await CallLogModel.sync(); await MessageLogModel.sync(); await AdminConfigModel.sync(); await CacheModel.sync(); } } function getAnalyticsVariablesInReqHeaders({ headers }) { const hashedExtensionId = headers['rc-extension-id']; const hashedAccountId = headers['rc-account-id']; const ip = headers['x-forwarded-for']?.split(',')?.find(i => !i.startsWith('10.')); const userAgent = headers['user-agent']; const author = headers['developer-author-name']; const eventAddedVia = headers['eventAddedVia']; return { hashedAccountId, hashedExtensionId, ip, userAgent, author, eventAddedVia } } // Create a router with all core routes function createCoreRouter() { const router = express.Router(); // Move all app.get, app.post, etc. to router.get, router.post, etc. router.get('/releaseNotes', async function (req, res) { const globalReleaseNotes = releaseNotes; const adapterReleaseNotes = adapterRegistry.getReleaseNotes(); const mergedReleaseNotes = {}; const versions = Object.keys(adapterReleaseNotes); for (const version of versions) { mergedReleaseNotes[version] = { global: globalReleaseNotes[version]?.global ?? {}, ...adapterReleaseNotes[version] ?? {} }; } res.json(mergedReleaseNotes); }); router.get('/crmManifest', (req, res) => { try { const platformName = req.query.platformName || 'default'; const crmManifest = adapterRegistry.getManifest(platformName); if (crmManifest) { // Override app server url for local development if (process.env.OVERRIDE_APP_SERVER) { crmManifest.serverUrl = process.env.OVERRIDE_APP_SERVER; } // Override server side logging server url for local development if (process.env.OVERRIDE_SERVER_SIDE_LOGGING_SERVER && crmManifest.platforms) { Object.keys(crmManifest.platforms).forEach(platformName => { const platform = crmManifest.platforms[platformName]; if (platform.serverSideLogging) { platform.serverSideLogging.url = process.env.OVERRIDE_SERVER_SIDE_LOGGING_SERVER; } }); } if (!crmManifest.author?.name) { throw 'author name is required'; } res.json(crmManifest); } else { res.status(400).send('Platform not found'); } } catch (e) { res.status(400).send('Platform not found'); } }); router.get('/is-alive', (req, res) => { res.send(`OK`); }); router.get('/authValidation', async (req, res) => { const requestStartTime = new Date().getTime(); let platformName = null; let success = false; let validationPass = false; let reason = ''; let statusCode = 200; const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers }) try { const jwtToken = req.query.jwtToken; if (jwtToken) { const decodedToken = jwt.decodeJwt(jwtToken); if (!decodedToken) { res.status(400).send('Invalid JWT token'); return; } const { id: userId, platform } = decodedToken; platformName = platform; const { successful, returnMessage, failReason, status } = await authCore.authValidation({ platform, userId }); success = true; validationPass = successful; reason = failReason; statusCode = status; res.status(200).send({ successful, returnMessage }); } else { res.status(400).send('Please go to Settings and authorize CRM platform'); success = false; } } catch (e) { console.log(`platform: ${platformName} \n${e.stack}`); statusCode = e.response?.status ?? 'unknown'; res.status(400).send(e); success = false; } const requestEndTime = new Date().getTime(); analytics.track({ eventName: 'Auth validation', interfaceName: 'authValidation', adapterName: platformName, rcAccountId: hashedAccountId, extensionId: hashedExtensionId, success, requestDuration: (requestEndTime - requestStartTime) / 1000, userAgent, ip, author, extras: { validationPass, reason, statusCode }, eventAddedVia }); }); router.get('/serverVersionInfo', (req, res) => { const defaultCrmManifest = adapterRegistry.getManifest('default'); res.send({ version: defaultCrmManifest?.version ?? 'unknown' }); }); router.post('/admin/settings', async function (req, res) { const requestStartTime = new Date().getTime(); let success = false; const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers }) try { const { isValidated, rcAccountId } = await adminCore.validateAdminRole({ rcAccessToken: req.query.rcAccessToken }); const hashedRcAccountId = util.getHashValue(rcAccountId, process.env.HASH_KEY); if (isValidated) { await adminCore.upsertAdminSettings({ hashedRcAccountId, adminSettings: req.body.adminSettings }); res.status(200).send('Admin settings updated'); success = true; } else { res.status(401).send('Admin validation failed'); success = false; } } catch (e) { console.log(`${e.stack}`); res.status(400).send(e); } const requestEndTime = new Date().getTime(); analytics.track({ eventName: 'Set admin settings', interfaceName: 'setAdminSettings', rcAccountId: hashedAccountId, extensionId: hashedExtensionId, success, requestDuration: (requestEndTime - requestStartTime) / 1000, userAgent, ip, author, eventAddedVia }); }); router.get('/admin/settings', async function (req, res) { const requestStartTime = new Date().getTime(); let platformName = null; let success = false; const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers }) try { const jwtToken = req.query.jwtToken; if (jwtToken) { const unAuthData = jwt.decodeJwt(jwtToken); platformName = unAuthData?.platform ?? 'Unknown'; const user = await UserModel.findByPk(unAuthData?.id); if (!user) { res.status(400).send('User not found'); return; } const { isValidated, rcAccountId } = await adminCore.validateAdminRole({ rcAccessToken: req.query.rcAccessToken }); const hashedRcAccountId = util.getHashValue(rcAccountId, process.env.HASH_KEY); if (isValidated) { const adminSettings = await adminCore.getAdminSettings({ hashedRcAccountId }); if (adminSettings) { res.status(200).send(adminSettings); } else { res.status(200).send({ customAdapter: null, userSettings: {} }); } success = true; } else { res.status(401).send('Admin validation failed'); success = true; } } else { res.status(400).send('Please go to Settings and authorize CRM platform'); success = false; } } catch (e) { res.status(400).send(e); } const requestEndTime = new Date().getTime(); analytics.track({ eventName: 'Get admin settings', interfaceName: 'getAdminSettings', adapterName: platformName, rcAccountId: hashedAccountId, extensionId: hashedExtensionId, success, requestDuration: (requestEndTime - requestStartTime) / 1000, userAgent, ip, author, eventAddedVia }); }); router.get('/admin/serverLoggingSettings', async function (req, res) { const requestStartTime = new Date().getTime(); let platformName = null; let success = false; const jwtToken = req.query.jwtToken; if (!jwtToken) { res.status(400).send('Please go to Settings and authorize CRM platform'); return; } const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers }) try { const unAuthData = jwt.decodeJwt(jwtToken); if (!unAuthData?.id) { res.status(400).send('Please go to Settings and authorize CRM platform'); return; } platformName = unAuthData?.platform ?? 'Unknown'; const user = await UserModel.findByPk(unAuthData?.id); if (!user) { res.status(400).send('User not found'); return; } const serverLoggingSettings = await adminCore.getServerLoggingSettings({ user }); res.status(200).send(serverLoggingSettings); success = true; } catch (e) { console.log(`${e.stack}`); res.status(400).send(e); } const requestEndTime = new Date().getTime(); analytics.track({ eventName: 'Get server logging settings', interfaceName: 'getServerLoggingSettings', adapterName: platformName, rcAccountId: hashedAccountId, extensionId: hashedExtensionId, success, requestDuration: (requestEndTime - requestStartTime) / 1000, userAgent, ip, author, eventAddedVia }); }); router.post('/admin/serverLoggingSettings', async function (req, res) { const requestStartTime = new Date().getTime(); let platformName = null; let success = false; const jwtToken = req.query.jwtToken; if (!jwtToken) { res.status(400).send('Please go to Settings and authorize CRM platform'); return; } if (!req.body.additionalFieldValues) { res.status(400).send('Missing additionalFieldValues'); return; } const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers }) try { const unAuthData = jwt.decodeJwt(jwtToken); if (!unAuthData?.id) { res.status(400).send('Please go to Settings and authorize CRM platform'); return; } platformName = unAuthData?.platform ?? 'Unknown'; const user = await UserModel.findByPk(unAuthData?.id); if (!user) { res.status(400).send('User not found'); return; } const serverLoggingSettings = await adminCore.updateServerLoggingSettings({ user, additionalFieldValues: req.body.additionalFieldValues }); res.status(200).send(serverLoggingSettings); success = true; } catch (e) { console.log(`${e.stack}`); res.status(400).send(e); success = false; } const requestEndTime = new Date().getTime(); analytics.track({ eventName: 'Set server logging settings', interfaceName: 'setServerLoggingSettings', adapterName: platformName, rcAccountId: hashedAccountId, extensionId: hashedExtensionId, success, requestDuration: (requestEndTime - requestStartTime) / 1000, userAgent, ip, author, eventAddedVia }); }) router.get('/user/preloadSettings', async function (req, res) { try { const rcAccessToken = req.query.rcAccessToken; const rcAccountId = req.query.rcAccountId; if (rcAccessToken || rcAccountId) { const userSettings = await userCore.getUserSettingsByAdmin({ rcAccessToken, rcAccountId }); res.status(200).send(userSettings); } else { res.status(400).send('Cannot find rc user login'); } } catch (e) { console.log(`${e.stack}`); res.status(400).send(e); } } ); router.get('/user/settings', async function (req, res) { const requestStartTime = new Date().getTime(); let platformName = null; let success = false; const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers }) try { const jwtToken = req.query.jwtToken; if (jwtToken) { const unAuthData = jwt.decodeJwt(jwtToken); platformName = unAuthData?.platform ?? 'Unknown'; const user = await UserModel.findByPk(unAuthData?.id); if (!user) { res.status(400).send('User not found'); return; } else { const rcAccessToken = req.query.rcAccessToken; const rcAccountId = req.query.rcAccountId; const userSettings = await userCore.getUserSettings({ user, rcAccessToken, rcAccountId }); success = true; res.status(200).send(userSettings); } } else { success = false; res.status(400).send('Please go to Settings and authorize CRM platform'); } } catch (e) { console.log(`platform: ${platformName} \n${e.stack}`); } const requestEndTime = new Date().getTime(); analytics.track({ eventName: 'Get user settings', interfaceName: 'getUserSettings', adapterName: platformName, rcAccountId: hashedAccountId, extensionId: hashedExtensionId, success, requestDuration: (requestEndTime - requestStartTime) / 1000, userAgent, ip, author, eventAddedVia }); }); router.post('/user/settings', async function (req, res) { const requestStartTime = new Date().getTime(); let platformName = null; let success = false; const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers }) try { const jwtToken = req.query.jwtToken; if (jwtToken) { const unAuthData = jwt.decodeJwt(jwtToken); platformName = unAuthData?.platform; if (!platformName) { res.status(400).send('Unknown platform'); } const user = await UserModel.findByPk(unAuthData?.id); if (!user) { res.status(400).send(); } const { userSettings } = await userCore.updateUserSettings({ user, userSettings: req.body.userSettings, platformName }); res.status(200).send({ userSettings }); success = true; } else { res.status(400).send('Please go to Settings and authorize CRM platform'); success = false; } } catch (e) { console.log(`platform: ${platformName} \n${e.stack}`); } const requestEndTime = new Date().getTime(); analytics.track({ eventName: 'Set user settings', interfaceName: 'setUserSettings', adapterName: platformName, rcAccountId: hashedAccountId, extensionId: hashedExtensionId, success, requestDuration: (requestEndTime - requestStartTime) / 1000, userAgent, ip, author, eventAddedVia }); }); router.get('/hostname', async function (req, res) { try { const jwtToken = req.query.jwtToken; if (jwtToken) { const unAuthData = jwt.decodeJwt(jwtToken); const user = await UserModel.findByPk(unAuthData?.id); if (!user) { res.status(400).send(); return; } res.status(200).send(user.hostname); } else { res.status(400).send('Please go to Settings and authorize CRM platform'); } } catch (e) { console.log(`${e.stack}`); res.status(500).send(e); } }) router.get('/oauth-callback', async function (req, res) { const requestStartTime = new Date().getTime(); let platformName = null; let success = false; const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers }) try { if (!req.query?.callbackUri || req.query.callbackUri === 'undefined') { throw 'Missing callbackUri'; } platformName = req.query.state ? req.query.state.split('platform=')[1] : decodeURIComponent(req.originalUrl).split('state=')[1].split('&')[0].split('platform=')[1]; const hostname = req.query.hostname; const tokenUrl = req.query.tokenUrl; if (!platformName) { throw 'Missing platform name'; } const hasAuthCodeInCallbackUri = req.query.callbackUri.includes('code='); if (!hasAuthCodeInCallbackUri) { // eslint-disable-next-line no-param-reassign req.query.callbackUri = `${req.query.callbackUri}&code=${req.query.code}`; } const { userInfo, returnMessage } = await authCore.onOAuthCallback({ platform: platformName, hostname, tokenUrl, callbackUri: req.query.callbackUri, apiUrl: req.query.apiUrl, username: req.query.username, query: req.query }); if (userInfo) { const jwtToken = jwt.generateJwt({ id: userInfo.id.toString(), platform: platformName }); res.status(200).send({ jwtToken, name: userInfo.name, returnMessage }); success = true; } else { res.status(200).send({ returnMessage }); success = false; } } catch (e) { console.log(`platform: ${platformName} \n${e.stack}`); res.status(400).send(e); success = false; } const requestEndTime = new Date().getTime(); analytics.track({ eventName: 'OAuth Callback', interfaceName: 'onOAuthCallback', adapterName: platformName, rcAccountId: hashedAccountId, extensionId: hashedExtensionId, success, requestDuration: (requestEndTime - requestStartTime) / 1000, userAgent, ip, author, eventAddedVia }); }) router.post('/apiKeyLogin', async function (req, res) { const requestStartTime = new Date().getTime(); let platformName = null; let success = false; const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers }) try { const platform = req.body.platform; platformName = platform; const apiKey = req.body.apiKey; const hostname = req.body.hostname; const additionalInfo = req.body.additionalInfo; if (!platform) { throw 'Missing platform name'; } if (!apiKey) { throw 'Missing api key'; } const { userInfo, returnMessage } = await authCore.onApiKeyLogin({ platform, hostname, apiKey, additionalInfo }); if (userInfo) { const jwtToken = jwt.generateJwt({ id: userInfo.id.toString(), platform: platform }); res.status(200).send({ jwtToken, name: userInfo.name, returnMessage }); success = true; } else { res.status(400).send({ returnMessage }); success = false; } } catch (e) { console.log(`platform: ${platformName} \n${e.stack}`); res.status(400).send(e); success = false; } const requestEndTime = new Date().getTime(); analytics.track({ eventName: 'API Key Login', interfaceName: 'onApiKeyLogin', adapterName: platformName, rcAccountId: hashedAccountId, extensionId: hashedExtensionId, success, requestDuration: (requestEndTime - requestStartTime) / 1000, userAgent, ip, author, eventAddedVia }); }) router.post('/unAuthorize', async function (req, res) { const requestStartTime = new Date().getTime(); let platformName = null; let success = false; const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers }) try { const jwtToken = req.query.jwtToken; if (jwtToken) { const unAuthData = jwt.decodeJwt(jwtToken); platformName = unAuthData?.platform ?? 'Unknown'; const userToLogout = await UserModel.findByPk(unAuthData?.id); if (!userToLogout) { res.status(400).send(); return; } const platformModule = adapterRegistry.getAdapter(unAuthData?.platform ?? 'Unknown'); const { returnMessage } = await platformModule.unAuthorize({ user: userToLogout }); res.status(200).send({ returnMessage }); success = true; } else { res.status(400).send('Please go to Settings and authorize CRM platform'); success = false; } } catch (e) { console.log(`platform: ${platformName} \n${e.stack}`); res.status(400).send(e); success = false; } const requestEndTime = new Date().getTime(); analytics.track({ eventName: 'Unauthorize', interfaceName: 'unAuthorize', adapterName: platformName, rcAccountId: hashedAccountId, extensionId: hashedExtensionId, success, requestDuration: (requestEndTime - requestStartTime) / 1000, userAgent, ip, author, eventAddedVia }); }); router.get('/userInfoHash', async function (req, res) { try { const extensionId = util.getHashValue(req.query.extensionId, process.env.HASH_KEY); const accountId = util.getHashValue(req.query.accountId, process.env.HASH_KEY); res.status(200).send({ extensionId, accountId }); } catch (e) { console.log(`${e.stack}`); res.status(400).send(e); } }) router.get('/contact', async function (req, res) { const requestStartTime = new Date().getTime(); let platformName = null; let success = false; let resultCount = 0; let extraData = {}; const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers }) try { const jwtToken = req.query.jwtToken; if (jwtToken) { const decodedToken = jwt.decodeJwt(jwtToken); if (!decodedToken) { res.status(400).send('Please go to Settings and authorize CRM platform'); return; } const { id: userId, platform } = decodedToken; platformName = platform; const { successful, returnMessage, contact, extraDataTracking } = await contactCore.findContact({ platform, userId, phoneNumber: req.query.phoneNumber.replace(' ', '+'), overridingFormat: req.query.overridingFormat, isExtension: req.query?.isExtension ?? false }); res.status(200).send({ successful, returnMessage, contact }); if (successful) { const nonNewContact = contact?.filter(c => !c.isNewContact) ?? []; resultCount = nonNewContact.length; } success = successful; if (extraDataTracking) { extraData = extraDataTracking; } } else { res.status(400).send('Please go to Settings and authorize CRM platform'); success = false; } } catch (e) { console.log(`platform: ${platformName} \n${e.stack}`); extraData.statusCode = e.response?.status ?? 'unknown'; res.status(400).send(e); success = false; } const requestEndTime = new Date().getTime(); analytics.track({ eventName: 'Find contact', interfaceName: 'findContact', adapterName: platformName, rcAccountId: hashedAccountId, extensionId: hashedExtensionId, success, requestDuration: (requestEndTime - requestStartTime) / 1000, userAgent, ip, author, extras: { resultCount, ...extraData }, eventAddedVia }); }); router.post('/contact', async function (req, res) { const requestStartTime = new Date().getTime(); let platformName = null; let success = false; let extraData = {}; const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers }) try { const jwtToken = req.query.jwtToken; if (jwtToken) { const decodedToken = jwt.decodeJwt(jwtToken); if (!decodedToken) { res.status(400).send('Please go to Settings and authorize CRM platform'); return; } const { id: userId, platform } = decodedToken; platformName = platform; 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 }); res.status(200).send({ successful, returnMessage, contact }); success = true; if (extraDataTracking) { extraData = extraDataTracking; } } else { res.status(400).send('Please go to Settings and authorize CRM platform'); success = false; } } catch (e) { console.log(`platform: ${platformName} \n${e.stack}`); extraData.statusCode = e.response?.status ?? 'unknown'; res.status(400).send(e); success = false; } const requestEndTime = new Date().getTime(); analytics.track({ eventName: 'Create contact', interfaceName: 'createContact', adapterName: platformName, rcAccountId: hashedAccountId, extensionId: hashedExtensionId, success, requestDuration: (requestEndTime - requestStartTime) / 1000, userAgent, ip, author, extras: { ...extraData }, eventAddedVia }); }); router.get('/callLog', async function (req, res) { const requestStartTime = new Date().getTime(); let platformName = null; let success = false; let extraData = {}; const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers }) try { const jwtToken = req.query.jwtToken; if (jwtToken) { const decodedToken = jwt.decodeJwt(jwtToken); if (!decodedToken) { res.status(400).send('Please go to Settings and authorize CRM platform'); return; } const { id: userId, platform } = decodedToken; platformName = platform; const { successful, logs, returnMessage, extraDataTracking } = await logCore.getCallLog({ userId, sessionIds: req.query.sessionIds, platform, requireDetails: req.query.requireDetails === 'true' }); res.status(200).send({ successful, logs, returnMessage }); success = true; if (extraDataTracking) { extraData = extraDataTracking; } } else { res.status(400).send('Please go to Settings and authorize CRM platform'); success = false; } } catch (e) { console.log(`platform: ${platformName} \n${e.stack}`); extraData.statusCode = e.response?.status ?? 'unknown'; res.status(400).send(e); success = false; } const requestEndTime = new Date().getTime(); analytics.track({ eventName: 'Get call log', interfaceName: 'getCallLog', adapterName: platformName, rcAccountId: hashedAccountId, extensionId: hashedExtensionId, success, requestDuration: (requestEndTime - requestStartTime) / 1000, userAgent, ip, author, extras: { ...extraData }, eventAddedVia }); }); router.post('/callLog', async function (req, res) { const requestStartTime = new Date().getTime(); let platformName = null; let success = false; let extraData = {}; const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers }) try { const jwtToken = req.query.jwtToken; if (jwtToken) { const decodedToken = jwt.decodeJwt(jwtToken); if (!decodedToken) { res.status(400).send('Please go to Settings and authorize CRM platform'); return; } const { id: userId, platform } = decodedToken; platformName = platform; const { successful, logId, returnMessage, extraDataTracking } = await logCore.createCallLog({ platform, userId, incomingData: req.body }); if (extraDataTracking) { extraData = extraDataTracking; } res.status(200).send({ successful, logId, returnMessage }); success = true; } else { res.status(400).send('Please go to Settings and authorize CRM platform'); success = false; } } catch (e) { console.log(`platform: ${platformName} \n${e.stack}`); extraData.statusCode = e.response?.status ?? 'unknown'; res.status(400).send(e); success = false; } const requestEndTime = new Date().getTime(); analytics.track({ eventName: 'Create call log', interfaceName: 'createCallLog', adapterName: platformName, rcAccountId: hashedAccountId, extensionId: hashedExtensionId, success, requestDuration: (requestEndTime - requestStartTime) / 1000, userAgent, ip, author, extras: { ...extraData }, eventAddedVia }); }); router.patch('/callLog', async function (req, res) { const requestStartTime = new Date().getTime(); let platformName = null; let success = false; let extraData = {}; const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers }) try { const jwtToken = req.query.jwtToken; if (jwtToken) { const decodedToken = jwt.decodeJwt(jwtToken); if (!decodedToken) { res.status(400).send('Please go to Settings and authorize CRM platform'); return; } const { id: userId, platform } = decodedToken; platformName = platform; const { successful, logId, updatedNote, returnMessage, extraDataTracking } = await logCore.updateCallLog({ platform, userId, incomingData: req.body }); if (extraDataTracking) { extraData = extraDataTracking; } res.status(200).send({ successful, logId, updatedNote, returnMessage }); success = true; } else { res.status(400).send('Please go to Settings and authorize CRM platform'); success = false; } } catch (e) { console.log(`platform: ${platformName} \n${e.stack}`); extraData.statusCode = e.response?.status ?? 'unknown'; res.status(400).send(e); success = false; } const requestEndTime = new Date().getTime(); analytics.track({ eventName: 'Update call log', interfaceName: 'updateCallLog', adapterName: platformName, rcAccountId: hashedAccountId, extensionId: hashedExtensionId, success, requestDuration: (requestEndTime - requestStartTime) / 1000, userAgent, ip, author, extras: { ...extraData }, eventAddedVia }); }); router.put('/callDisposition', async function (req, res) { const requestStartTime = new Date().getTime(); let platformName = null; let success = false; let extraData = {}; const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers }) try { const jwtToken = req.query.jwtToken; if (jwtToken) { const { id: userId, platform } = jwt.decodeJwt(jwtToken); platformName = platform; if (!userId) { res.status(400).send(); } const { successful, returnMessage, extraDataTracking } = await dispositionCore.upsertCallDisposition({ platform, userId, sessionId: req.body.sessionId, dispositions: req.body.dispositions, additionalSubmission: req.body.additionalSubmission }); if (extraDataTracking) { extraData = extraDataTracking; } res.status(200).send({ successful, returnMessage }); success = true; } else { res.status(400).send('Please go to Settings and authorize CRM platform'); success = false; } } catch (e) { console.log(`platform: ${platformName} \n${e.stack}`); extraData.statusCode = e.response?.status ?? 'unknown'; res.status(400).send(e); success = false; } const requestEndTime = new Date().getTime(); analytics.track({ eventName: 'Create call log', interfaceName: 'createCallLog', adapterName: platformName, rcAccountId: hashedAccountId, extensionId: hashedExtensionId, success, requestDuration: (requestEndTime - requestStartTime) / 1000, userAgent, ip, author, extras: { ...extraData }, eventAddedVia }); }); router.post('/messageLog', async function (req, res) { const requestStartTime = new Date().getTime(); let platformName = null; let success = false; let statusCode = 200; let extraData = {}; const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers }) try { const jwtToken = req.query.jwtToken; if (jwtToken) { const decodedToken = jwt.decodeJwt(jwtToken); if (!decodedToken) { res.status(400).send('Please go to Settings and authorize CRM platform'); return; } const { id: userId, platform } = decodedToken; platformName = platform; const { successful, returnMessage, logIds, extraDataTracking } = await logCore.createMessageLog({ platform, userId, incomingData: req.body }); if (extraDataTracking) { extraData = extraDataTracking; } res.status(200).send({ successful, returnMessage, logIds }); success = true; } else { res.status(400).send('Please go to Settings and authorize CRM platform'); success = false; } } catch (e) { console.log(`platform: ${platformName} \n${e.stack}`); statusCode = e.response?.status ?? 'unknown'; res.status(400).send(e); success = false; } const requestEndTime = new Date().getTime(); analytics.track({ eventName: 'Create message log', interfaceName: 'createMessageLog', adapterName: platformName, rcAccountId: hashedAccountId, extensionId: hashedExtensionId, success, requestDuration: (requestEndTime - requestStartTime) / 1000, userAgent, ip, author, extras: { statusCode, ...extraData }, eventAddedVia }); }); router.get('/custom/contact/search', async function (req, res) { const requestStartTime = new Date().getTime(); let platformName = null; let success = false; let resultCount = 0; let statusCode = 200; const { hashedExtensionId, hashedAccountId, userAgent, ip, author } = getAnalyticsVariablesInReqHeaders({ headers: req.headers }) try { const jwtToken = req.query.jwtToken; if (jwtToken) { const { id: userId, platform } = jwt.decodeJwt(jwtToken); platformName = platform; const { successful, returnMessage, contact } = await contactCore.findContactWithName({ platform, userId, name: req.query.name }); res.status(200).send({ successful, returnMessage, contact }); success = successful; } else { res.status(400).send('Please go to Settings and authorize CRM platform'); success = false; } } catch (e) { console.log(`platform: ${platformName} \n${e.stack}`); statusCode = e.response?.status ?? 'unknown'; res.status(400).send(e); success = false; } const requestEndTime = new Date().getTime(); analytics.track({ eventName: 'Contact Search by Name', interfaceName: 'contactSearchByName', adapterName: platformName, rcAccountId: hashedAccountId, extensionId: hashedExtensionId, success, requestDuration: (requestEndTime - requestStartTime) / 1000, userAgent, ip, author, extras: { statusCode } }); }); if (process.env.IS_PROD === 'false') { router.post('/registerMockUser', async function (req, res) { const secretKey = req.query.secretKey; if (secretKey === process.env.APP_SERVER_SECRET_KEY) { const mockUser = await mock.createUser({ userName: req.body.userName }); res.status(200).send(mockUser ? 'Mock user registered' : 'Mock user already existed'); } else { res.status(401).send('Unauthorized'); } }); router.delete('/deleteMockUser', async function (req, res) { const secretKey = req.query.secretKey; if (secretKey === process.env.APP_SERVER_SECRET_KEY) { const foundAndDeleted = await mock.deleteUser({ userName: req.query.userName }); res.status(200).send(foundAndDeleted ? 'Mock user deleted' : 'Mock user not found'); } else { res.status(401).send('Unauthorized'); } }); router.get('/mockCallLog', async function (req, res) { const secretKey = req.query.secretKey; if (secretKey === process.env.APP_SERVER_SECRET_KEY) { const callLogs = await mock.getCallLog({ sessionIds: req.query.sessionIds }); res.status(200).send(callLogs); } else { res.status(401).send('Unauthorized'); } }); router.post('/mockCallLog', async function (req, res) { const secretKey = req.query.secretKey; if (secretKey === process.env.APP_SERVER_SECRET_KEY) { await mock.createCallLog({ sessionId: req.body.sessionId }); res.status(200).send('Mock call log created'); } else { res.status(401).send('Unauthorized'); } }); router.delete('/mockCallLog', async function (req, res) { const secretKey = req.query.secretKey; if (secretKey === process.env.APP_SERVER_SECRET_KEY) { await mock.cleanUpMockLogs(); res.status(200).send('Mock call logs cleaned up'); } else { res.status(401).send('Unauthorized'); } }); } return router; } // Create middleware for core functionality function createCoreMiddleware() { return [ bodyParser.json(), cors({ methods: ['GET', 'POST', 'PATCH', 'PUT'] }) ]; } // Initialize core services async function initializeCore(options = {}) { const { skipDatabaseInit = false, skipAnalyticsInit = false, } = options; if (!skipAnalyticsInit) { analytics.init(); } if (!skipDatabaseInit) { await initDB(); } } // Create a complete app with core functionality function createCoreApp(options = {}) { initializeCore(options); const app = express(); // Apply core middleware const coreMiddleware = createCoreMiddleware(); coreMiddleware.forEach(middleware => app.use(middleware)); // Apply core routes const coreRouter = createCoreRouter(); app.use('/', coreRouter); return app; } exports.createCoreRouter = createCoreRouter; exports.createCoreMiddleware = createCoreMiddleware; exports.createCoreApp = createCoreApp; exports.initializeCore = initializeCore; exports.adapterRegistry = adapterRegistry;