@app-connect/core 1.5.8 → 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/.env.test +5 -5
- package/README.md +434 -434
- package/adapter/mock.js +76 -76
- package/adapter/registry.js +247 -247
- package/handlers/admin.js +62 -60
- package/handlers/auth.js +205 -156
- package/handlers/contact.js +274 -274
- package/handlers/disposition.js +193 -193
- package/handlers/log.js +612 -587
- package/handlers/user.js +101 -101
- package/index.js +1302 -1204
- package/jest.config.js +56 -56
- package/lib/analytics.js +52 -52
- package/lib/callLogComposer.js +550 -485
- package/lib/constants.js +8 -8
- package/lib/encode.js +30 -30
- package/lib/generalErrorMessage.js +41 -41
- package/lib/jwt.js +16 -16
- package/lib/oauth.js +34 -21
- package/lib/util.js +43 -40
- package/models/adminConfigModel.js +17 -17
- package/models/cacheModel.js +23 -23
- package/models/callLogModel.js +27 -27
- package/models/dynamo/lockSchema.js +24 -24
- package/models/dynamo/noteCacheSchema.js +30 -0
- package/models/messageLogModel.js +25 -25
- package/models/sequelize.js +16 -16
- package/models/userModel.js +38 -38
- package/package.json +67 -64
- package/releaseNotes.json +701 -605
- package/test/adapter/registry.test.js +270 -270
- package/test/handlers/auth.test.js +230 -230
- package/test/lib/jwt.test.js +161 -161
- package/test/setup.js +176 -176
package/lib/constants.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
const LOG_DETAILS_FORMAT_TYPE = {
|
|
2
|
-
PLAIN_TEXT: 'text/plain',
|
|
3
|
-
HTML: 'text/html',
|
|
4
|
-
MARKDOWN: 'text/markdown'
|
|
5
|
-
};
|
|
6
|
-
|
|
7
|
-
module.exports = {
|
|
8
|
-
LOG_DETAILS_FORMAT_TYPE
|
|
1
|
+
const LOG_DETAILS_FORMAT_TYPE = {
|
|
2
|
+
PLAIN_TEXT: 'text/plain',
|
|
3
|
+
HTML: 'text/html',
|
|
4
|
+
MARKDOWN: 'text/markdown'
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
module.exports = {
|
|
8
|
+
LOG_DETAILS_FORMAT_TYPE
|
|
9
9
|
};
|
package/lib/encode.js
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
const crypto = require('crypto');
|
|
2
|
-
|
|
3
|
-
function getCipherKey() {
|
|
4
|
-
if (!process.env.APP_SERVER_SECRET_KEY) {
|
|
5
|
-
throw new Error('APP_SERVER_SECRET_KEY is not defined');
|
|
6
|
-
}
|
|
7
|
-
if (process.env.APP_SERVER_SECRET_KEY.length < 32) {
|
|
8
|
-
// pad secret key with spaces if it is less than 32 bytes
|
|
9
|
-
return process.env.APP_SERVER_SECRET_KEY.padEnd(32, ' ');
|
|
10
|
-
}
|
|
11
|
-
if (process.env.APP_SERVER_SECRET_KEY.length > 32) {
|
|
12
|
-
// truncate secret key if it is more than 32 bytes
|
|
13
|
-
return process.env.APP_SERVER_SECRET_KEY.slice(0, 32);
|
|
14
|
-
}
|
|
15
|
-
return process.env.APP_SERVER_SECRET_KEY;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function encode(data) {
|
|
19
|
-
const cipher = crypto.createCipheriv('aes-256-cbc', getCipherKey(), Buffer.alloc(16, 0));
|
|
20
|
-
return cipher.update(data, 'utf8', 'hex') + cipher.final('hex');
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function decoded(encryptedData) {
|
|
24
|
-
const decipher = crypto.createDecipheriv('aes-256-cbc', getCipherKey(), Buffer.alloc(16, 0));
|
|
25
|
-
return decipher.update(encryptedData, 'hex', 'utf8') + decipher.final('utf8');
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
exports.encode = encode;
|
|
30
|
-
exports.decoded = decoded;
|
|
1
|
+
const crypto = require('crypto');
|
|
2
|
+
|
|
3
|
+
function getCipherKey() {
|
|
4
|
+
if (!process.env.APP_SERVER_SECRET_KEY) {
|
|
5
|
+
throw new Error('APP_SERVER_SECRET_KEY is not defined');
|
|
6
|
+
}
|
|
7
|
+
if (process.env.APP_SERVER_SECRET_KEY.length < 32) {
|
|
8
|
+
// pad secret key with spaces if it is less than 32 bytes
|
|
9
|
+
return process.env.APP_SERVER_SECRET_KEY.padEnd(32, ' ');
|
|
10
|
+
}
|
|
11
|
+
if (process.env.APP_SERVER_SECRET_KEY.length > 32) {
|
|
12
|
+
// truncate secret key if it is more than 32 bytes
|
|
13
|
+
return process.env.APP_SERVER_SECRET_KEY.slice(0, 32);
|
|
14
|
+
}
|
|
15
|
+
return process.env.APP_SERVER_SECRET_KEY;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function encode(data) {
|
|
19
|
+
const cipher = crypto.createCipheriv('aes-256-cbc', getCipherKey(), Buffer.alloc(16, 0));
|
|
20
|
+
return cipher.update(data, 'utf8', 'hex') + cipher.final('hex');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function decoded(encryptedData) {
|
|
24
|
+
const decipher = crypto.createDecipheriv('aes-256-cbc', getCipherKey(), Buffer.alloc(16, 0));
|
|
25
|
+
return decipher.update(encryptedData, 'hex', 'utf8') + decipher.final('utf8');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
exports.encode = encode;
|
|
30
|
+
exports.decoded = decoded;
|
|
@@ -1,42 +1,42 @@
|
|
|
1
|
-
function rateLimitErrorMessage({ platform }) {
|
|
2
|
-
return {
|
|
3
|
-
message: `Rate limit exceeded`,
|
|
4
|
-
messageType: 'warning',
|
|
5
|
-
details: [
|
|
6
|
-
{
|
|
7
|
-
title: 'Details',
|
|
8
|
-
items: [
|
|
9
|
-
{
|
|
10
|
-
id: '1',
|
|
11
|
-
type: 'text',
|
|
12
|
-
text: `You have exceeded the maximum number of requests allowed by ${platform}. Please try again in the next minute. If the problem persists please contact support.`
|
|
13
|
-
}
|
|
14
|
-
]
|
|
15
|
-
}
|
|
16
|
-
],
|
|
17
|
-
ttl: 5000
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function authorizationErrorMessage({ platform }) {
|
|
22
|
-
return {
|
|
23
|
-
message: `Authorization error`,
|
|
24
|
-
messageType: 'warning',
|
|
25
|
-
details: [
|
|
26
|
-
{
|
|
27
|
-
title: 'Details',
|
|
28
|
-
items: [
|
|
29
|
-
{
|
|
30
|
-
id: '1',
|
|
31
|
-
type: 'text',
|
|
32
|
-
text: `It seems like there's something wrong with your authorization of ${platform}. Please Logout and then Connect your ${platform} account within this extension.`
|
|
33
|
-
}
|
|
34
|
-
]
|
|
35
|
-
}
|
|
36
|
-
],
|
|
37
|
-
ttl: 5000
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
exports.rateLimitErrorMessage = rateLimitErrorMessage;
|
|
1
|
+
function rateLimitErrorMessage({ platform }) {
|
|
2
|
+
return {
|
|
3
|
+
message: `Rate limit exceeded`,
|
|
4
|
+
messageType: 'warning',
|
|
5
|
+
details: [
|
|
6
|
+
{
|
|
7
|
+
title: 'Details',
|
|
8
|
+
items: [
|
|
9
|
+
{
|
|
10
|
+
id: '1',
|
|
11
|
+
type: 'text',
|
|
12
|
+
text: `You have exceeded the maximum number of requests allowed by ${platform}. Please try again in the next minute. If the problem persists please contact support.`
|
|
13
|
+
}
|
|
14
|
+
]
|
|
15
|
+
}
|
|
16
|
+
],
|
|
17
|
+
ttl: 5000
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function authorizationErrorMessage({ platform }) {
|
|
22
|
+
return {
|
|
23
|
+
message: `Authorization error`,
|
|
24
|
+
messageType: 'warning',
|
|
25
|
+
details: [
|
|
26
|
+
{
|
|
27
|
+
title: 'Details',
|
|
28
|
+
items: [
|
|
29
|
+
{
|
|
30
|
+
id: '1',
|
|
31
|
+
type: 'text',
|
|
32
|
+
text: `It seems like there's something wrong with your authorization of ${platform}. Please Logout and then Connect your ${platform} account within this extension.`
|
|
33
|
+
}
|
|
34
|
+
]
|
|
35
|
+
}
|
|
36
|
+
],
|
|
37
|
+
ttl: 5000
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
exports.rateLimitErrorMessage = rateLimitErrorMessage;
|
|
42
42
|
exports.authorizationErrorMessage = authorizationErrorMessage;
|
package/lib/jwt.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
const { sign, verify } = require('jsonwebtoken');
|
|
2
|
-
|
|
3
|
-
function generateJwt(data) {
|
|
4
|
-
return sign(data, process.env.APP_SERVER_SECRET_KEY, { expiresIn: '120y' })
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
function decodeJwt(token) {
|
|
8
|
-
try {
|
|
9
|
-
return verify(token, process.env.APP_SERVER_SECRET_KEY);
|
|
10
|
-
} catch (e) {
|
|
11
|
-
return null;
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
exports.generateJwt = generateJwt;
|
|
16
|
-
exports.decodeJwt = decodeJwt;
|
|
1
|
+
const { sign, verify } = require('jsonwebtoken');
|
|
2
|
+
|
|
3
|
+
function generateJwt(data) {
|
|
4
|
+
return sign(data, process.env.APP_SERVER_SECRET_KEY, { expiresIn: '120y' })
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function decodeJwt(token) {
|
|
8
|
+
try {
|
|
9
|
+
return verify(token, process.env.APP_SERVER_SECRET_KEY);
|
|
10
|
+
} catch (e) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
exports.generateJwt = generateJwt;
|
|
16
|
+
exports.decodeJwt = decodeJwt;
|
package/lib/oauth.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/* eslint-disable no-param-reassign */
|
|
2
2
|
const ClientOAuth2 = require('client-oauth2');
|
|
3
|
+
const moment = require('moment');
|
|
3
4
|
const { UserModel } = require('../models/userModel');
|
|
4
5
|
const adapterRegistry = require('../adapter/registry');
|
|
5
6
|
const dynamoose = require('dynamoose');
|
|
@@ -18,10 +19,10 @@ function getOAuthApp({ clientId, clientSecret, accessTokenUri, authorizationUri,
|
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
|
|
21
|
-
async function checkAndRefreshAccessToken(oauthApp, user, tokenLockTimeout =
|
|
22
|
-
const
|
|
23
|
-
const tokenExpiry =
|
|
24
|
-
const expiryBuffer =
|
|
22
|
+
async function checkAndRefreshAccessToken(oauthApp, user, tokenLockTimeout = 20) {
|
|
23
|
+
const now = moment();
|
|
24
|
+
const tokenExpiry = moment(user.tokenExpiry);
|
|
25
|
+
const expiryBuffer = 2; // 2 minutes
|
|
25
26
|
// Special case: Bullhorn
|
|
26
27
|
if (user.platform) {
|
|
27
28
|
const platformModule = adapterRegistry.getAdapter(user.platform);
|
|
@@ -29,21 +30,21 @@ async function checkAndRefreshAccessToken(oauthApp, user, tokenLockTimeout = 10)
|
|
|
29
30
|
return platformModule.checkAndRefreshAccessToken(oauthApp, user, tokenLockTimeout);
|
|
30
31
|
}
|
|
31
32
|
}
|
|
32
|
-
// Other CRMs
|
|
33
|
-
if (user && user.accessToken && user.refreshToken && tokenExpiry.
|
|
34
|
-
let newLock;
|
|
33
|
+
// Other CRMs - check if token will expire within the buffer time
|
|
34
|
+
if (user && user.accessToken && user.refreshToken && tokenExpiry.isBefore(now.clone().add(expiryBuffer, 'minutes'))) {
|
|
35
35
|
// case: use dynamoDB to manage token refresh lock
|
|
36
|
-
if (
|
|
36
|
+
if (adapterRegistry.getManifest('default')?.platforms?.[user.platform]?.auth?.useTokenRefreshLock) {
|
|
37
|
+
let newLock;
|
|
37
38
|
const { Lock } = require('../models/dynamo/lockSchema');
|
|
38
39
|
// Try to atomically create lock only if it doesn't exist
|
|
39
40
|
try {
|
|
40
41
|
newLock = await Lock.create(
|
|
41
|
-
{
|
|
42
|
+
{
|
|
42
43
|
userId: user.id,
|
|
43
|
-
ttl:
|
|
44
|
-
|
|
45
|
-
{
|
|
46
|
-
|
|
44
|
+
ttl: now.unix() + 30
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
overwrite: false
|
|
47
48
|
}
|
|
48
49
|
);
|
|
49
50
|
console.log('lock created')
|
|
@@ -51,14 +52,18 @@ async function checkAndRefreshAccessToken(oauthApp, user, tokenLockTimeout = 10)
|
|
|
51
52
|
// If creation failed due to condition, a lock exists
|
|
52
53
|
if (e.name === 'ConditionalCheckFailedException' || e.__type === 'com.amazonaws.dynamodb.v20120810#ConditionalCheckFailedException') {
|
|
53
54
|
let lock = await Lock.get({ userId: user.id });
|
|
54
|
-
if (!!lock?.ttl && lock.ttl <
|
|
55
|
+
if (!!lock?.ttl && moment(lock.ttl).unix() < now.unix()) {
|
|
55
56
|
// Try to delete expired lock and create a new one atomically
|
|
56
57
|
try {
|
|
58
|
+
console.log('lock expired.')
|
|
57
59
|
await lock.delete();
|
|
58
60
|
newLock = await Lock.create(
|
|
59
|
-
{
|
|
60
|
-
|
|
61
|
-
|
|
61
|
+
{
|
|
62
|
+
userId: user.id,
|
|
63
|
+
ttl: now.unix() + 30
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
overwrite: false
|
|
62
67
|
}
|
|
63
68
|
);
|
|
64
69
|
} catch (e2) {
|
|
@@ -70,12 +75,15 @@ async function checkAndRefreshAccessToken(oauthApp, user, tokenLockTimeout = 10)
|
|
|
70
75
|
}
|
|
71
76
|
}
|
|
72
77
|
}
|
|
73
|
-
|
|
78
|
+
|
|
74
79
|
if (lock && !newLock) {
|
|
75
80
|
let processTime = 0;
|
|
81
|
+
let delay = 500; // Start with 500ms
|
|
82
|
+
const maxDelay = 8000; // Cap at 8 seconds
|
|
76
83
|
while (!!lock && processTime < tokenLockTimeout) {
|
|
77
|
-
await new Promise(resolve => setTimeout(resolve,
|
|
78
|
-
processTime +=
|
|
84
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
85
|
+
processTime += delay / 1000; // Convert to seconds for comparison
|
|
86
|
+
delay = Math.min(delay * 2, maxDelay); // Exponential backoff with cap
|
|
79
87
|
lock = await Lock.get({ userId: user.id });
|
|
80
88
|
}
|
|
81
89
|
// Timeout -> let users try another time
|
|
@@ -90,6 +98,7 @@ async function checkAndRefreshAccessToken(oauthApp, user, tokenLockTimeout = 10)
|
|
|
90
98
|
throw e;
|
|
91
99
|
}
|
|
92
100
|
}
|
|
101
|
+
const startRefreshTime = moment();
|
|
93
102
|
const token = oauthApp.createToken(user.accessToken, user.refreshToken);
|
|
94
103
|
console.log('token refreshing...')
|
|
95
104
|
const { accessToken, refreshToken, expires } = await token.refresh();
|
|
@@ -98,9 +107,13 @@ async function checkAndRefreshAccessToken(oauthApp, user, tokenLockTimeout = 10)
|
|
|
98
107
|
user.tokenExpiry = expires;
|
|
99
108
|
await user.save();
|
|
100
109
|
if (newLock) {
|
|
110
|
+
const deletionStartTime = moment();
|
|
101
111
|
await newLock.delete();
|
|
112
|
+
const deletionEndTime = moment();
|
|
113
|
+
console.log(`lock deleted in ${deletionEndTime.diff(deletionStartTime)}ms`)
|
|
102
114
|
}
|
|
103
|
-
|
|
115
|
+
const endRefreshTime = moment();
|
|
116
|
+
console.log(`token refreshing finished in ${endRefreshTime.diff(startRefreshTime)}ms`)
|
|
104
117
|
}
|
|
105
118
|
// case: run withou token refresh lock
|
|
106
119
|
else {
|
package/lib/util.js
CHANGED
|
@@ -1,40 +1,43 @@
|
|
|
1
|
-
|
|
2
|
-
const tzlookup = require('tz-lookup');
|
|
3
|
-
const { State } = require('country-state-city');
|
|
4
|
-
const crypto = require('crypto');
|
|
5
|
-
|
|
6
|
-
function getTimeZone(countryCode, stateCode) {
|
|
7
|
-
const state = State.getStateByCodeAndCountry(stateCode, countryCode);
|
|
8
|
-
if (!state) {
|
|
9
|
-
return 'Unknown timezone';
|
|
10
|
-
}
|
|
11
|
-
const timezone = tzlookup(state.latitude, state.longitude);
|
|
12
|
-
return timezone;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
function getHashValue(string, secretKey) {
|
|
17
|
-
return crypto.createHash('sha256').update(
|
|
18
|
-
`${string}:${secretKey}`
|
|
19
|
-
).digest('hex');
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function secondsToHoursMinutesSeconds(seconds) {
|
|
23
|
-
// If not a number, return the input directly
|
|
24
|
-
if (isNaN(seconds)) {
|
|
25
|
-
return seconds;
|
|
26
|
-
}
|
|
27
|
-
const hours = Math.floor(seconds / 3600);
|
|
28
|
-
const hoursString = hours > 0 ? `${hours} ${hours > 1 ? 'hours' : 'hour'}` : '';
|
|
29
|
-
const minutes = Math.floor((seconds % 3600) / 60);
|
|
30
|
-
const minutesString = minutes > 0 ? `${minutes} ${minutes > 1 ? 'minutes' : 'minute'}` : '';
|
|
31
|
-
const remainingSeconds = seconds % 60;
|
|
32
|
-
const secondsString = remainingSeconds > 0 ? `${remainingSeconds} ${remainingSeconds > 1 ? 'seconds' : 'second'}` : '';
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
1
|
+
|
|
2
|
+
const tzlookup = require('tz-lookup');
|
|
3
|
+
const { State } = require('country-state-city');
|
|
4
|
+
const crypto = require('crypto');
|
|
5
|
+
|
|
6
|
+
function getTimeZone(countryCode, stateCode) {
|
|
7
|
+
const state = State.getStateByCodeAndCountry(stateCode, countryCode);
|
|
8
|
+
if (!state) {
|
|
9
|
+
return 'Unknown timezone';
|
|
10
|
+
}
|
|
11
|
+
const timezone = tzlookup(state.latitude, state.longitude);
|
|
12
|
+
return timezone;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
function getHashValue(string, secretKey) {
|
|
17
|
+
return crypto.createHash('sha256').update(
|
|
18
|
+
`${string}:${secretKey}`
|
|
19
|
+
).digest('hex');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function secondsToHoursMinutesSeconds(seconds) {
|
|
23
|
+
// If not a number, return the input directly
|
|
24
|
+
if (isNaN(seconds)) {
|
|
25
|
+
return seconds;
|
|
26
|
+
}
|
|
27
|
+
const hours = Math.floor(seconds / 3600);
|
|
28
|
+
const hoursString = hours > 0 ? `${hours} ${hours > 1 ? 'hours' : 'hour'}` : '';
|
|
29
|
+
const minutes = Math.floor((seconds % 3600) / 60);
|
|
30
|
+
const minutesString = minutes > 0 ? `${minutes} ${minutes > 1 ? 'minutes' : 'minute'}` : '';
|
|
31
|
+
const remainingSeconds = seconds % 60;
|
|
32
|
+
const secondsString = remainingSeconds > 0 ? `${remainingSeconds} ${remainingSeconds > 1 ? 'seconds' : 'second'}` : '';
|
|
33
|
+
if (!hoursString && !minutesString && !secondsString) {
|
|
34
|
+
return '0 seconds';
|
|
35
|
+
}
|
|
36
|
+
const resultString = [hoursString, minutesString, secondsString].filter(Boolean).join(', ');
|
|
37
|
+
return resultString;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
exports.getTimeZone = getTimeZone;
|
|
41
|
+
exports.getHashValue = getHashValue;
|
|
42
|
+
exports.secondsToHoursMinutesSeconds = secondsToHoursMinutesSeconds;
|
|
43
|
+
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
const Sequelize = require('sequelize');
|
|
2
|
-
const { sequelize } = require('./sequelize');
|
|
3
|
-
|
|
4
|
-
// Model for User data
|
|
5
|
-
exports.AdminConfigModel = sequelize.define('adminConfigs', {
|
|
6
|
-
// hashed rc account ID
|
|
7
|
-
id: {
|
|
8
|
-
type: Sequelize.STRING,
|
|
9
|
-
primaryKey: true,
|
|
10
|
-
},
|
|
11
|
-
userSettings: {
|
|
12
|
-
type: Sequelize.JSON
|
|
13
|
-
},
|
|
14
|
-
customAdapter: {
|
|
15
|
-
type: Sequelize.JSON
|
|
16
|
-
}
|
|
17
|
-
});
|
|
1
|
+
const Sequelize = require('sequelize');
|
|
2
|
+
const { sequelize } = require('./sequelize');
|
|
3
|
+
|
|
4
|
+
// Model for User data
|
|
5
|
+
exports.AdminConfigModel = sequelize.define('adminConfigs', {
|
|
6
|
+
// hashed rc account ID
|
|
7
|
+
id: {
|
|
8
|
+
type: Sequelize.STRING,
|
|
9
|
+
primaryKey: true,
|
|
10
|
+
},
|
|
11
|
+
userSettings: {
|
|
12
|
+
type: Sequelize.JSON
|
|
13
|
+
},
|
|
14
|
+
customAdapter: {
|
|
15
|
+
type: Sequelize.JSON
|
|
16
|
+
}
|
|
17
|
+
});
|
package/models/cacheModel.js
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
const Sequelize = require('sequelize');
|
|
2
|
-
const { sequelize } = require('./sequelize');
|
|
3
|
-
|
|
4
|
-
// Model for cache data
|
|
5
|
-
exports.CacheModel = sequelize.define('cache', {
|
|
6
|
-
// id = {userId}-{cacheKey}
|
|
7
|
-
id: {
|
|
8
|
-
type: Sequelize.STRING,
|
|
9
|
-
primaryKey: true,
|
|
10
|
-
},
|
|
11
|
-
status: {
|
|
12
|
-
type: Sequelize.STRING,
|
|
13
|
-
},
|
|
14
|
-
userId: {
|
|
15
|
-
type: Sequelize.STRING,
|
|
16
|
-
},
|
|
17
|
-
cacheKey: {
|
|
18
|
-
type: Sequelize.STRING,
|
|
19
|
-
},
|
|
20
|
-
expiry: {
|
|
21
|
-
type: Sequelize.DATE
|
|
22
|
-
}
|
|
23
|
-
});
|
|
1
|
+
const Sequelize = require('sequelize');
|
|
2
|
+
const { sequelize } = require('./sequelize');
|
|
3
|
+
|
|
4
|
+
// Model for cache data
|
|
5
|
+
exports.CacheModel = sequelize.define('cache', {
|
|
6
|
+
// id = {userId}-{cacheKey}
|
|
7
|
+
id: {
|
|
8
|
+
type: Sequelize.STRING,
|
|
9
|
+
primaryKey: true,
|
|
10
|
+
},
|
|
11
|
+
status: {
|
|
12
|
+
type: Sequelize.STRING,
|
|
13
|
+
},
|
|
14
|
+
userId: {
|
|
15
|
+
type: Sequelize.STRING,
|
|
16
|
+
},
|
|
17
|
+
cacheKey: {
|
|
18
|
+
type: Sequelize.STRING,
|
|
19
|
+
},
|
|
20
|
+
expiry: {
|
|
21
|
+
type: Sequelize.DATE
|
|
22
|
+
}
|
|
23
|
+
});
|
package/models/callLogModel.js
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
const Sequelize = require('sequelize');
|
|
2
|
-
const { sequelize } = require('./sequelize');
|
|
3
|
-
|
|
4
|
-
// Model for User data
|
|
5
|
-
exports.CallLogModel = sequelize.define('callLogs', {
|
|
6
|
-
// callId
|
|
7
|
-
id: {
|
|
8
|
-
type: Sequelize.STRING,
|
|
9
|
-
primaryKey: true,
|
|
10
|
-
},
|
|
11
|
-
sessionId: {
|
|
12
|
-
type: Sequelize.STRING,
|
|
13
|
-
primaryKey: true,
|
|
14
|
-
},
|
|
15
|
-
platform: {
|
|
16
|
-
type: Sequelize.STRING,
|
|
17
|
-
},
|
|
18
|
-
thirdPartyLogId: {
|
|
19
|
-
type: Sequelize.STRING,
|
|
20
|
-
},
|
|
21
|
-
userId: {
|
|
22
|
-
type: Sequelize.STRING,
|
|
23
|
-
},
|
|
24
|
-
contactId: {
|
|
25
|
-
type: Sequelize.STRING,
|
|
26
|
-
}
|
|
27
|
-
});
|
|
1
|
+
const Sequelize = require('sequelize');
|
|
2
|
+
const { sequelize } = require('./sequelize');
|
|
3
|
+
|
|
4
|
+
// Model for User data
|
|
5
|
+
exports.CallLogModel = sequelize.define('callLogs', {
|
|
6
|
+
// callId
|
|
7
|
+
id: {
|
|
8
|
+
type: Sequelize.STRING,
|
|
9
|
+
primaryKey: true,
|
|
10
|
+
},
|
|
11
|
+
sessionId: {
|
|
12
|
+
type: Sequelize.STRING,
|
|
13
|
+
primaryKey: true,
|
|
14
|
+
},
|
|
15
|
+
platform: {
|
|
16
|
+
type: Sequelize.STRING,
|
|
17
|
+
},
|
|
18
|
+
thirdPartyLogId: {
|
|
19
|
+
type: Sequelize.STRING,
|
|
20
|
+
},
|
|
21
|
+
userId: {
|
|
22
|
+
type: Sequelize.STRING,
|
|
23
|
+
},
|
|
24
|
+
contactId: {
|
|
25
|
+
type: Sequelize.STRING,
|
|
26
|
+
}
|
|
27
|
+
});
|
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
const dynamoose = require('dynamoose');
|
|
2
|
-
|
|
3
|
-
const lockSchema = new dynamoose.Schema({
|
|
4
|
-
userId: {
|
|
5
|
-
type: String,
|
|
6
|
-
hashKey: true
|
|
7
|
-
},
|
|
8
|
-
ttl: {
|
|
9
|
-
type: Number
|
|
10
|
-
}
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
const tableOptions = {
|
|
14
|
-
prefix: process.env.DYNAMODB_TABLE_PREFIX,
|
|
15
|
-
expires: 60 // 60 seconds
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
if (process.env.NODE_ENV === 'production') {
|
|
19
|
-
tableOptions.create = false;
|
|
20
|
-
tableOptions.waitForActive = false;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const Lock = dynamoose.model('-token-refresh-lock', lockSchema, tableOptions);
|
|
24
|
-
|
|
1
|
+
const dynamoose = require('dynamoose');
|
|
2
|
+
|
|
3
|
+
const lockSchema = new dynamoose.Schema({
|
|
4
|
+
userId: {
|
|
5
|
+
type: String,
|
|
6
|
+
hashKey: true
|
|
7
|
+
},
|
|
8
|
+
ttl: {
|
|
9
|
+
type: Number
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const tableOptions = {
|
|
14
|
+
prefix: process.env.DYNAMODB_TABLE_PREFIX,
|
|
15
|
+
expires: 60 // 60 seconds
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
if (process.env.NODE_ENV === 'production') {
|
|
19
|
+
tableOptions.create = false;
|
|
20
|
+
tableOptions.waitForActive = false;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const Lock = dynamoose.model('-token-refresh-lock', lockSchema, tableOptions);
|
|
24
|
+
|
|
25
25
|
exports.Lock = Lock;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
const dynamoose = require('dynamoose');
|
|
2
|
+
|
|
3
|
+
const noteCacheSchema = new dynamoose.Schema({
|
|
4
|
+
sessionId: {
|
|
5
|
+
type: String,
|
|
6
|
+
hashKey: true,
|
|
7
|
+
},
|
|
8
|
+
note: {
|
|
9
|
+
type: String,
|
|
10
|
+
required: true,
|
|
11
|
+
},
|
|
12
|
+
ttl: {
|
|
13
|
+
type: Number,
|
|
14
|
+
required: true,
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
const tableOptions = {
|
|
19
|
+
prefix: process.env.DYNAMODB_TABLE_PREFIX,
|
|
20
|
+
expires: 60 // 60 seconds
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
if (process.env.NODE_ENV === 'production') {
|
|
24
|
+
tableOptions.create = false;
|
|
25
|
+
tableOptions.waitForActive = false;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const NoteCache = dynamoose.model('-note-cache', noteCacheSchema, tableOptions);
|
|
29
|
+
|
|
30
|
+
exports.NoteCache = NoteCache;
|
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
const Sequelize = require('sequelize');
|
|
2
|
-
const { sequelize } = require('./sequelize');
|
|
3
|
-
|
|
4
|
-
// Model for User data
|
|
5
|
-
exports.MessageLogModel = sequelize.define('messageLogs', {
|
|
6
|
-
id: {
|
|
7
|
-
type: Sequelize.STRING,
|
|
8
|
-
primaryKey: true,
|
|
9
|
-
},
|
|
10
|
-
platform: {
|
|
11
|
-
type: Sequelize.STRING,
|
|
12
|
-
},
|
|
13
|
-
conversationId: {
|
|
14
|
-
type: Sequelize.STRING,
|
|
15
|
-
},
|
|
16
|
-
conversationLogId:{
|
|
17
|
-
type: Sequelize.STRING,
|
|
18
|
-
},
|
|
19
|
-
thirdPartyLogId: {
|
|
20
|
-
type: Sequelize.STRING,
|
|
21
|
-
},
|
|
22
|
-
userId: {
|
|
23
|
-
type: Sequelize.STRING,
|
|
24
|
-
}
|
|
25
|
-
});
|
|
1
|
+
const Sequelize = require('sequelize');
|
|
2
|
+
const { sequelize } = require('./sequelize');
|
|
3
|
+
|
|
4
|
+
// Model for User data
|
|
5
|
+
exports.MessageLogModel = sequelize.define('messageLogs', {
|
|
6
|
+
id: {
|
|
7
|
+
type: Sequelize.STRING,
|
|
8
|
+
primaryKey: true,
|
|
9
|
+
},
|
|
10
|
+
platform: {
|
|
11
|
+
type: Sequelize.STRING,
|
|
12
|
+
},
|
|
13
|
+
conversationId: {
|
|
14
|
+
type: Sequelize.STRING,
|
|
15
|
+
},
|
|
16
|
+
conversationLogId:{
|
|
17
|
+
type: Sequelize.STRING,
|
|
18
|
+
},
|
|
19
|
+
thirdPartyLogId: {
|
|
20
|
+
type: Sequelize.STRING,
|
|
21
|
+
},
|
|
22
|
+
userId: {
|
|
23
|
+
type: Sequelize.STRING,
|
|
24
|
+
}
|
|
25
|
+
});
|