@app-connect/core 1.7.10 → 1.7.11
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/connector/developerPortal.js +43 -0
- package/connector/proxy/index.js +10 -3
- package/connector/registry.js +8 -6
- package/handlers/admin.js +44 -21
- package/handlers/auth.js +89 -67
- package/handlers/calldown.js +10 -4
- package/handlers/contact.js +4 -104
- package/handlers/disposition.js +4 -142
- package/handlers/log.js +172 -257
- package/handlers/user.js +19 -6
- package/index.js +213 -47
- package/lib/analytics.js +3 -1
- package/lib/authSession.js +68 -0
- package/lib/callLogComposer.js +498 -420
- package/lib/errorHandler.js +206 -0
- package/lib/jwt.js +2 -0
- package/lib/logger.js +190 -0
- package/lib/oauth.js +21 -10
- package/lib/ringcentral.js +2 -10
- package/lib/sharedSMSComposer.js +471 -0
- package/mcp/SupportedPlatforms.md +12 -0
- package/mcp/lib/validator.js +91 -0
- package/mcp/mcpHandler.js +166 -0
- package/mcp/tools/checkAuthStatus.js +90 -0
- package/mcp/tools/collectAuthInfo.js +86 -0
- package/mcp/tools/createCallLog.js +299 -0
- package/mcp/tools/createMessageLog.js +283 -0
- package/mcp/tools/doAuth.js +185 -0
- package/mcp/tools/findContactByName.js +87 -0
- package/mcp/tools/findContactByPhone.js +96 -0
- package/mcp/tools/getCallLog.js +98 -0
- package/mcp/tools/getHelp.js +39 -0
- package/mcp/tools/getPublicConnectors.js +46 -0
- package/mcp/tools/index.js +58 -0
- package/mcp/tools/logout.js +63 -0
- package/mcp/tools/rcGetCallLogs.js +73 -0
- package/mcp/tools/setConnector.js +64 -0
- package/mcp/tools/updateCallLog.js +122 -0
- package/models/cacheModel.js +3 -0
- package/package.json +71 -70
- package/releaseNotes.json +12 -0
- package/test/handlers/log.test.js +6 -2
- package/test/lib/logger.test.js +206 -0
- package/test/lib/sharedSMSComposer.test.js +1084 -0
- package/test/mcp/tools/collectAuthInfo.test.js +192 -0
- package/test/mcp/tools/createCallLog.test.js +412 -0
- package/test/mcp/tools/createMessageLog.test.js +580 -0
- package/test/mcp/tools/doAuth.test.js +363 -0
- package/test/mcp/tools/findContactByName.test.js +263 -0
- package/test/mcp/tools/findContactByPhone.test.js +284 -0
- package/test/mcp/tools/getCallLog.test.js +286 -0
- package/test/mcp/tools/getPublicConnectors.test.js +128 -0
- package/test/mcp/tools/logout.test.js +169 -0
- package/test/mcp/tools/setConnector.test.js +177 -0
- package/test/mcp/tools/updateCallLog.test.js +346 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const axios = require('axios');
|
|
2
|
+
const { logger } = require('../lib/logger');
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
async function getPublicConnectorList() {
|
|
6
|
+
try {
|
|
7
|
+
const response = await axios.get('https://appconnect.labs.ringcentral.com/public-api/connectors');
|
|
8
|
+
return response.data;
|
|
9
|
+
} catch (error) {
|
|
10
|
+
logger.error('Error getting public connector list:', error);
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async function getPrivateConnectorList() {
|
|
16
|
+
try {
|
|
17
|
+
const response = await axios.get(`https://appconnect.labs.ringcentral.com/public-api/connectors/internal?accountId=${process.env.RC_ACCOUNT_ID}`);
|
|
18
|
+
return response.data;
|
|
19
|
+
} catch (error) {
|
|
20
|
+
logger.error('Error getting private connector list:', error);
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async function getConnectorManifest({connectorId, isPrivate = false}) {
|
|
26
|
+
try {
|
|
27
|
+
let response = null;
|
|
28
|
+
if(isPrivate) {
|
|
29
|
+
response = await axios.get(`https://appconnect.labs.ringcentral.com/public-api/connectors/${connectorId}/manifest?type=internal&accountId=${process.env.RC_ACCOUNT_ID}`);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
response = await axios.get(`https://appconnect.labs.ringcentral.com/public-api/connectors/${connectorId}/manifest`);
|
|
33
|
+
}
|
|
34
|
+
return response.data;
|
|
35
|
+
} catch (error) {
|
|
36
|
+
logger.error('Error getting connector manifest:', error);
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
exports.getPublicConnectorList = getPublicConnectorList;
|
|
42
|
+
exports.getPrivateConnectorList = getPrivateConnectorList;
|
|
43
|
+
exports.getConnectorManifest = getConnectorManifest;
|
package/connector/proxy/index.js
CHANGED
|
@@ -10,6 +10,8 @@ const {
|
|
|
10
10
|
} = require('./engine');
|
|
11
11
|
const { Connector } = require('../../models/dynamo/connectorSchema');
|
|
12
12
|
const { UserModel } = require('../../models/userModel');
|
|
13
|
+
const logger = require('../../lib/logger');
|
|
14
|
+
const { handleDatabaseError } = require('../../lib/errorHandler');
|
|
13
15
|
|
|
14
16
|
async function loadPlatformConfig(proxyId) {
|
|
15
17
|
if (!proxyId) {
|
|
@@ -19,7 +21,7 @@ async function loadPlatformConfig(proxyId) {
|
|
|
19
21
|
const proxyConfig = await Connector.getProxyConfig(proxyId);
|
|
20
22
|
return proxyConfig;
|
|
21
23
|
} catch (error) {
|
|
22
|
-
|
|
24
|
+
logger.error('Error getting proxy config: ', { proxyId, stack: error.stack });
|
|
23
25
|
return null;
|
|
24
26
|
}
|
|
25
27
|
}
|
|
@@ -32,7 +34,7 @@ async function getAuthType({ proxyId, proxyConfig } = {}) {
|
|
|
32
34
|
return cfg.auth.type || 'apiKey';
|
|
33
35
|
}
|
|
34
36
|
|
|
35
|
-
async function getOauthInfo({ proxyId, proxyConfig, tokenUrl
|
|
37
|
+
async function getOauthInfo({ proxyId, proxyConfig, tokenUrl } = {}) {
|
|
36
38
|
const cfg = proxyConfig ? proxyConfig : (await loadPlatformConfig(proxyId));
|
|
37
39
|
if (!cfg) {
|
|
38
40
|
return {};
|
|
@@ -146,7 +148,12 @@ async function unAuthorize({ user }) {
|
|
|
146
148
|
}
|
|
147
149
|
user.accessToken = '';
|
|
148
150
|
user.refreshToken = '';
|
|
149
|
-
|
|
151
|
+
try {
|
|
152
|
+
await user.save();
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
return handleDatabaseError(error, 'Error saving user');
|
|
156
|
+
}
|
|
150
157
|
return {
|
|
151
158
|
successful: true,
|
|
152
159
|
returnMessage: {
|
package/connector/registry.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// core/src/connector/registry.js
|
|
2
|
+
const logger = require('../lib/logger');
|
|
2
3
|
class ConnectorRegistry {
|
|
3
4
|
constructor() {
|
|
4
5
|
this.connectors = new Map();
|
|
@@ -29,7 +30,7 @@ class ConnectorRegistry {
|
|
|
29
30
|
const platformInterfaceMap = this.platformInterfaces.get(platformName);
|
|
30
31
|
platformInterfaceMap.set(interfaceName, interfaceFunction);
|
|
31
32
|
|
|
32
|
-
|
|
33
|
+
logger.info(`Registered interface function: ${platformName}.${interfaceName}`);
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
/**
|
|
@@ -61,7 +62,7 @@ class ConnectorRegistry {
|
|
|
61
62
|
const platformInterfaceMap = this.platformInterfaces.get(platformName);
|
|
62
63
|
if (platformInterfaceMap && platformInterfaceMap.has(interfaceName)) {
|
|
63
64
|
platformInterfaceMap.delete(interfaceName);
|
|
64
|
-
|
|
65
|
+
logger.info(`Unregistered interface function: ${platformName}.${interfaceName}`);
|
|
65
66
|
}
|
|
66
67
|
}
|
|
67
68
|
|
|
@@ -80,7 +81,7 @@ class ConnectorRegistry {
|
|
|
80
81
|
this.manifests.set(platform, manifest);
|
|
81
82
|
}
|
|
82
83
|
|
|
83
|
-
|
|
84
|
+
logger.info(`Registered connector: ${platform}`);
|
|
84
85
|
}
|
|
85
86
|
|
|
86
87
|
/**
|
|
@@ -109,7 +110,7 @@ class ConnectorRegistry {
|
|
|
109
110
|
composedConnector[interfaceName] = interfaceFunction;
|
|
110
111
|
}
|
|
111
112
|
|
|
112
|
-
|
|
113
|
+
logger.info(`Returning interface-only connector for platform: ${platform}`);
|
|
113
114
|
return composedConnector;
|
|
114
115
|
}
|
|
115
116
|
|
|
@@ -203,14 +204,14 @@ class ConnectorRegistry {
|
|
|
203
204
|
this.connectors.delete(platform);
|
|
204
205
|
this.manifests.delete(platform);
|
|
205
206
|
this.platformInterfaces.delete(platform);
|
|
206
|
-
|
|
207
|
+
logger.info(`Unregistered connector: ${platform}`);
|
|
207
208
|
}
|
|
208
209
|
|
|
209
210
|
setReleaseNotes(releaseNotes) {
|
|
210
211
|
this.releaseNotes = releaseNotes;
|
|
211
212
|
}
|
|
212
213
|
|
|
213
|
-
getReleaseNotes(
|
|
214
|
+
getReleaseNotes() {
|
|
214
215
|
return this.releaseNotes;
|
|
215
216
|
}
|
|
216
217
|
|
|
@@ -237,6 +238,7 @@ class ConnectorRegistry {
|
|
|
237
238
|
try {
|
|
238
239
|
capabilities.authType = await originalConnector.getAuthType();
|
|
239
240
|
} catch (error) {
|
|
241
|
+
logger.error('Error getting auth type', { stack: error.stack });
|
|
240
242
|
capabilities.authType = 'unknown';
|
|
241
243
|
}
|
|
242
244
|
}
|
package/handlers/admin.js
CHANGED
|
@@ -4,6 +4,8 @@ const connectorRegistry = require('../connector/registry');
|
|
|
4
4
|
const oauth = require('../lib/oauth');
|
|
5
5
|
const { RingCentral } = require('../lib/ringcentral');
|
|
6
6
|
const { Connector } = require('../models/dynamo/connectorSchema');
|
|
7
|
+
const logger = require('../lib/logger');
|
|
8
|
+
const { handleDatabaseError } = require('../lib/errorHandler');
|
|
7
9
|
|
|
8
10
|
const CALL_AGGREGATION_GROUPS = ["Company", "CompanyNumbers", "Users", "Queues", "IVRs", "IVAs", "SharedLines", "UserGroups", "Sites", "Departments"]
|
|
9
11
|
|
|
@@ -136,7 +138,7 @@ async function getAdminReport({ rcAccountId, timezone, timeFrom, timeTo, groupBy
|
|
|
136
138
|
groupKeys: CALL_AGGREGATION_GROUPS
|
|
137
139
|
};
|
|
138
140
|
} catch (error) {
|
|
139
|
-
|
|
141
|
+
logger.error('Error getting admin report', { error });
|
|
140
142
|
return {
|
|
141
143
|
callLogStats: {}
|
|
142
144
|
};
|
|
@@ -206,13 +208,19 @@ async function getUserReport({ rcAccountId, rcExtensionId, timezone, timeFrom, t
|
|
|
206
208
|
};
|
|
207
209
|
return reportStats;
|
|
208
210
|
} catch (error) {
|
|
209
|
-
|
|
211
|
+
logger.error('Error getting user report', { error });
|
|
210
212
|
return null;
|
|
211
213
|
}
|
|
212
214
|
}
|
|
213
215
|
|
|
214
216
|
async function getUserMapping({ user, hashedRcAccountId, rcExtensionList }) {
|
|
215
|
-
|
|
217
|
+
let adminConfig = null;
|
|
218
|
+
try {
|
|
219
|
+
adminConfig = await getAdminSettings({ hashedRcAccountId });
|
|
220
|
+
}
|
|
221
|
+
catch (error) {
|
|
222
|
+
return handleDatabaseError(error, 'Error getting user mapping');
|
|
223
|
+
}
|
|
216
224
|
const platformModule = connectorRegistry.getConnector(user.platform);
|
|
217
225
|
if (platformModule.getUserList) {
|
|
218
226
|
const proxyId = user.platformAdditionalInfo?.proxyId;
|
|
@@ -318,12 +326,17 @@ async function getUserMapping({ user, hashedRcAccountId, rcExtensionList }) {
|
|
|
318
326
|
});
|
|
319
327
|
}
|
|
320
328
|
}
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
329
|
+
try {
|
|
330
|
+
await upsertAdminSettings({
|
|
331
|
+
hashedRcAccountId,
|
|
332
|
+
adminSettings: {
|
|
333
|
+
userMappings: initialUserMappings
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
catch (error) {
|
|
338
|
+
return handleDatabaseError(error, 'Error initializing user mapping');
|
|
339
|
+
}
|
|
327
340
|
}
|
|
328
341
|
// Incremental update
|
|
329
342
|
if (newUserMappings.length > 0) {
|
|
@@ -333,20 +346,30 @@ async function getUserMapping({ user, hashedRcAccountId, rcExtensionList }) {
|
|
|
333
346
|
...u,
|
|
334
347
|
rcExtensionId: [u.rcExtensionId]
|
|
335
348
|
}));
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
349
|
+
try {
|
|
350
|
+
await upsertAdminSettings({
|
|
351
|
+
hashedRcAccountId,
|
|
352
|
+
adminSettings: {
|
|
353
|
+
userMappings: [...adminConfig.userMappings, ...newUserMappings]
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
catch (error) {
|
|
358
|
+
return handleDatabaseError(error, 'Error updating user mapping');
|
|
359
|
+
}
|
|
342
360
|
}
|
|
343
361
|
else {
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
362
|
+
try {
|
|
363
|
+
await upsertAdminSettings({
|
|
364
|
+
hashedRcAccountId,
|
|
365
|
+
adminSettings: {
|
|
366
|
+
userMappings: [...newUserMappings]
|
|
367
|
+
}
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
catch (error) {
|
|
371
|
+
return handleDatabaseError(error, 'Error updating user mapping');
|
|
372
|
+
}
|
|
350
373
|
}
|
|
351
374
|
}
|
|
352
375
|
return userMappingResult;
|
package/handlers/auth.js
CHANGED
|
@@ -5,8 +5,9 @@ const Op = require('sequelize').Op;
|
|
|
5
5
|
const { RingCentral } = require('../lib/ringcentral');
|
|
6
6
|
const adminCore = require('./admin');
|
|
7
7
|
const { Connector } = require('../models/dynamo/connectorSchema');
|
|
8
|
+
const { handleDatabaseError } = require('../lib/errorHandler');
|
|
8
9
|
|
|
9
|
-
async function onOAuthCallback({ platform, hostname, tokenUrl, query }) {
|
|
10
|
+
async function onOAuthCallback({ platform, hostname, tokenUrl, query, isFromMCP = false }) {
|
|
10
11
|
const callbackUri = query.callbackUri;
|
|
11
12
|
const apiUrl = query.apiUrl;
|
|
12
13
|
const username = query.username;
|
|
@@ -17,8 +18,7 @@ async function onOAuthCallback({ platform, hostname, tokenUrl, query }) {
|
|
|
17
18
|
if (proxyId) {
|
|
18
19
|
proxyConfig = await Connector.getProxyConfig(proxyId);
|
|
19
20
|
}
|
|
20
|
-
const oauthInfo = await platformModule.getOauthInfo({ tokenUrl, hostname, rcAccountId: query.rcAccountId, proxyId, proxyConfig, userEmail });
|
|
21
|
-
|
|
21
|
+
const oauthInfo = await platformModule.getOauthInfo({ tokenUrl, hostname, rcAccountId: query.rcAccountId, proxyId, proxyConfig, userEmail, isFromMCP });
|
|
22
22
|
if (oauthInfo.failMessage) {
|
|
23
23
|
return {
|
|
24
24
|
userInfo: null,
|
|
@@ -41,19 +41,25 @@ async function onOAuthCallback({ platform, hostname, tokenUrl, query }) {
|
|
|
41
41
|
const { successful, platformUserInfo, returnMessage } = await platformModule.getUserInfo({ authHeader, tokenUrl, apiUrl, hostname, platform, username, callbackUri, query, proxyId, proxyConfig, userEmail });
|
|
42
42
|
|
|
43
43
|
if (successful) {
|
|
44
|
-
let userInfo =
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
44
|
+
let userInfo = null;
|
|
45
|
+
try {
|
|
46
|
+
userInfo = await saveUserInfo({
|
|
47
|
+
platformUserInfo,
|
|
48
|
+
platform,
|
|
49
|
+
tokenUrl,
|
|
50
|
+
apiUrl,
|
|
51
|
+
username,
|
|
52
|
+
hostname: platformUserInfo?.overridingHostname ? platformUserInfo.overridingHostname : hostname,
|
|
53
|
+
accessToken,
|
|
54
|
+
refreshToken,
|
|
55
|
+
tokenExpiry: expires,
|
|
56
|
+
rcAccountId: query?.rcAccountId,
|
|
57
|
+
proxyId
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
return handleDatabaseError(error, 'Error saving user info');
|
|
62
|
+
}
|
|
57
63
|
if (platformModule.postSaveUserInfo) {
|
|
58
64
|
userInfo = await platformModule.postSaveUserInfo({ userInfo, oauthApp });
|
|
59
65
|
}
|
|
@@ -75,13 +81,19 @@ async function onApiKeyLogin({ platform, hostname, apiKey, proxyId, additionalIn
|
|
|
75
81
|
const basicAuth = platformModule.getBasicAuth({ apiKey });
|
|
76
82
|
const { successful, platformUserInfo, returnMessage } = await platformModule.getUserInfo({ authHeader: `Basic ${basicAuth}`, hostname, platform, additionalInfo, apiKey, proxyId });
|
|
77
83
|
if (successful) {
|
|
78
|
-
let userInfo =
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
84
|
+
let userInfo = null;
|
|
85
|
+
try {
|
|
86
|
+
userInfo = await saveUserInfo({
|
|
87
|
+
platformUserInfo,
|
|
88
|
+
platform,
|
|
89
|
+
hostname,
|
|
90
|
+
proxyId,
|
|
91
|
+
accessToken: platformUserInfo.overridingApiKey ?? apiKey
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
return handleDatabaseError(error, 'Error saving user info');
|
|
96
|
+
}
|
|
85
97
|
if (platformModule.postSaveUserInfo) {
|
|
86
98
|
userInfo = await platformModule.postSaveUserInfo({ userInfo });
|
|
87
99
|
}
|
|
@@ -107,43 +119,65 @@ async function saveUserInfo({ platformUserInfo, platform, hostname, accessToken,
|
|
|
107
119
|
const platformAdditionalInfo = platformUserInfo.platformAdditionalInfo || {};
|
|
108
120
|
platformAdditionalInfo.proxyId = proxyId;
|
|
109
121
|
if (existingUser) {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
timezoneName,
|
|
115
|
-
timezoneOffset,
|
|
116
|
-
accessToken,
|
|
117
|
-
refreshToken,
|
|
118
|
-
tokenExpiry,
|
|
119
|
-
rcAccountId,
|
|
120
|
-
platformAdditionalInfo: {
|
|
121
|
-
...existingUser.platformAdditionalInfo, // keep existing platformAdditionalInfo
|
|
122
|
-
...platformAdditionalInfo,
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
);
|
|
126
|
-
}
|
|
127
|
-
else {
|
|
128
|
-
// TEMP: replace user with old ID
|
|
129
|
-
if (id.endsWith(`-${platform}`)) {
|
|
130
|
-
const oldID = id.split('-');
|
|
131
|
-
const userWithOldID = await UserModel.findByPk(oldID[0]);
|
|
132
|
-
if (userWithOldID) {
|
|
133
|
-
await UserModel.create({
|
|
134
|
-
id,
|
|
122
|
+
try {
|
|
123
|
+
await existingUser.update(
|
|
124
|
+
{
|
|
125
|
+
platform,
|
|
135
126
|
hostname,
|
|
136
127
|
timezoneName,
|
|
137
128
|
timezoneOffset,
|
|
138
|
-
platform,
|
|
139
129
|
accessToken,
|
|
140
130
|
refreshToken,
|
|
141
131
|
tokenExpiry,
|
|
142
132
|
rcAccountId,
|
|
143
|
-
platformAdditionalInfo
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
133
|
+
platformAdditionalInfo: {
|
|
134
|
+
...existingUser.platformAdditionalInfo, // keep existing platformAdditionalInfo
|
|
135
|
+
...platformAdditionalInfo,
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
return handleDatabaseError(error, 'Error saving user info');
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
try {
|
|
146
|
+
// TEMP: replace user with old ID
|
|
147
|
+
if (id.endsWith(`-${platform}`)) {
|
|
148
|
+
const oldID = id.split('-');
|
|
149
|
+
const userWithOldID = await UserModel.findByPk(oldID[0]);
|
|
150
|
+
if (userWithOldID) {
|
|
151
|
+
await UserModel.create({
|
|
152
|
+
id,
|
|
153
|
+
hostname,
|
|
154
|
+
timezoneName,
|
|
155
|
+
timezoneOffset,
|
|
156
|
+
platform,
|
|
157
|
+
accessToken,
|
|
158
|
+
refreshToken,
|
|
159
|
+
tokenExpiry,
|
|
160
|
+
rcAccountId,
|
|
161
|
+
platformAdditionalInfo,
|
|
162
|
+
userSettings: userWithOldID.userSettings
|
|
163
|
+
});
|
|
164
|
+
await userWithOldID.destroy();
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
await UserModel.create({
|
|
168
|
+
id,
|
|
169
|
+
hostname,
|
|
170
|
+
timezoneName,
|
|
171
|
+
timezoneOffset,
|
|
172
|
+
platform,
|
|
173
|
+
accessToken,
|
|
174
|
+
refreshToken,
|
|
175
|
+
tokenExpiry,
|
|
176
|
+
rcAccountId,
|
|
177
|
+
platformAdditionalInfo,
|
|
178
|
+
userSettings: {}
|
|
179
|
+
});
|
|
180
|
+
}
|
|
147
181
|
}
|
|
148
182
|
else {
|
|
149
183
|
await UserModel.create({
|
|
@@ -161,20 +195,8 @@ async function saveUserInfo({ platformUserInfo, platform, hostname, accessToken,
|
|
|
161
195
|
});
|
|
162
196
|
}
|
|
163
197
|
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
id,
|
|
167
|
-
hostname,
|
|
168
|
-
timezoneName,
|
|
169
|
-
timezoneOffset,
|
|
170
|
-
platform,
|
|
171
|
-
accessToken,
|
|
172
|
-
refreshToken,
|
|
173
|
-
tokenExpiry,
|
|
174
|
-
rcAccountId,
|
|
175
|
-
platformAdditionalInfo,
|
|
176
|
-
userSettings: {}
|
|
177
|
-
});
|
|
198
|
+
catch (error) {
|
|
199
|
+
return handleDatabaseError(error, 'Error saving user info');
|
|
178
200
|
}
|
|
179
201
|
}
|
|
180
202
|
return {
|
package/handlers/calldown.js
CHANGED
|
@@ -2,8 +2,9 @@ const { UserModel } = require('../models/userModel');
|
|
|
2
2
|
const { CallDownListModel } = require('../models/callDownListModel');
|
|
3
3
|
const { Op } = require('sequelize');
|
|
4
4
|
const jwt = require('../lib/jwt');
|
|
5
|
+
const { handleDatabaseError } = require('../lib/errorHandler');
|
|
5
6
|
|
|
6
|
-
async function schedule({ jwtToken,
|
|
7
|
+
async function schedule({ jwtToken, body }) {
|
|
7
8
|
const unAuthData = jwt.decodeJwt(jwtToken);
|
|
8
9
|
if (!unAuthData?.id) throw new Error('Unauthorized');
|
|
9
10
|
const user = await UserModel.findByPk(unAuthData.id);
|
|
@@ -48,9 +49,14 @@ async function markCalled({ jwtToken, id, lastCallAt }) {
|
|
|
48
49
|
const unAuthData = jwt.decodeJwt(jwtToken);
|
|
49
50
|
if (!unAuthData?.id) throw new Error('Unauthorized');
|
|
50
51
|
const when = lastCallAt ? new Date(lastCallAt) : new Date();
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
try {
|
|
53
|
+
const [affected] = await CallDownListModel.update({ status: 'called', lastCallAt: when }, { where: { id, userId: unAuthData.id } });
|
|
54
|
+
if (!affected) throw new Error('Not found');
|
|
55
|
+
return { successful: true };
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
return handleDatabaseError(error, 'Error marking call as called', { id, userId: unAuthData.id });
|
|
59
|
+
}
|
|
54
60
|
}
|
|
55
61
|
|
|
56
62
|
async function update({ jwtToken, id, updateData }) {
|
package/handlers/contact.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
const oauth = require('../lib/oauth');
|
|
2
2
|
const { UserModel } = require('../models/userModel');
|
|
3
|
-
const errorMessage = require('../lib/generalErrorMessage');
|
|
4
3
|
const connectorRegistry = require('../connector/registry');
|
|
5
4
|
const { Connector } = require('../models/dynamo/connectorSchema');
|
|
6
|
-
const {
|
|
5
|
+
const { handleApiError } = require('../lib/errorHandler');
|
|
7
6
|
const { AccountDataModel } = require('../models/accountDataModel');
|
|
8
7
|
|
|
9
8
|
async function findContact({ platform, userId, phoneNumber, overridingFormat, isExtension, tracer, isForceRefreshAccountData = false }) {
|
|
@@ -126,51 +125,9 @@ async function findContact({ platform, userId, phoneNumber, overridingFormat, is
|
|
|
126
125
|
};
|
|
127
126
|
}
|
|
128
127
|
} catch (e) {
|
|
129
|
-
console.error(`platform: ${platform} \n${e.stack} \n${JSON.stringify(e.response?.data)}`);
|
|
130
128
|
tracer?.traceError('handler.findContact:error', e, { platform, statusCode: e.response?.status });
|
|
129
|
+
return handleApiError(e, platform, 'findContact', { userId, overridingFormat, isExtension });
|
|
131
130
|
|
|
132
|
-
if (e.response?.status === 429) {
|
|
133
|
-
return {
|
|
134
|
-
successful: false,
|
|
135
|
-
returnMessage: errorMessage.rateLimitErrorMessage({ platform }),
|
|
136
|
-
extraDataTracking: {
|
|
137
|
-
statusCode: e.response?.status,
|
|
138
|
-
}
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
else if (e.response?.status >= 400 && e.response?.status < 410) {
|
|
142
|
-
return {
|
|
143
|
-
successful: false,
|
|
144
|
-
returnMessage: errorMessage.authorizationErrorMessage({ platform }),
|
|
145
|
-
extraDataTracking: {
|
|
146
|
-
statusCode: e.response?.status,
|
|
147
|
-
}
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
return {
|
|
151
|
-
successful: false,
|
|
152
|
-
returnMessage:
|
|
153
|
-
{
|
|
154
|
-
message: `Error finding contacts`,
|
|
155
|
-
messageType: 'warning',
|
|
156
|
-
details: [
|
|
157
|
-
{
|
|
158
|
-
title: 'Details',
|
|
159
|
-
items: [
|
|
160
|
-
{
|
|
161
|
-
id: '1',
|
|
162
|
-
type: 'text',
|
|
163
|
-
text: `Please check if your account has permission to VIEW and LIST contacts`
|
|
164
|
-
}
|
|
165
|
-
]
|
|
166
|
-
}
|
|
167
|
-
],
|
|
168
|
-
ttl: 5000
|
|
169
|
-
},
|
|
170
|
-
extraDataTracking: {
|
|
171
|
-
statusCode: e.response?.status,
|
|
172
|
-
}
|
|
173
|
-
};
|
|
174
131
|
}
|
|
175
132
|
}
|
|
176
133
|
|
|
@@ -212,43 +169,7 @@ async function createContact({ platform, userId, phoneNumber, newContactName, ne
|
|
|
212
169
|
return { successful: false, returnMessage };
|
|
213
170
|
}
|
|
214
171
|
} catch (e) {
|
|
215
|
-
|
|
216
|
-
if (e.response?.status === 429) {
|
|
217
|
-
return {
|
|
218
|
-
successful: false,
|
|
219
|
-
returnMessage: errorMessage.rateLimitErrorMessage({ platform }),
|
|
220
|
-
};
|
|
221
|
-
}
|
|
222
|
-
else if (e.response?.status >= 400 && e.response?.status < 410) {
|
|
223
|
-
return {
|
|
224
|
-
successful: false,
|
|
225
|
-
returnMessage: errorMessage.authorizationErrorMessage({ platform }),
|
|
226
|
-
extraDataTracking: {
|
|
227
|
-
statusCode: e.response?.status,
|
|
228
|
-
}
|
|
229
|
-
};
|
|
230
|
-
}
|
|
231
|
-
return {
|
|
232
|
-
successful: false,
|
|
233
|
-
returnMessage:
|
|
234
|
-
{
|
|
235
|
-
message: `Error creating contact`,
|
|
236
|
-
messageType: 'warning',
|
|
237
|
-
details: [
|
|
238
|
-
{
|
|
239
|
-
title: 'Details',
|
|
240
|
-
items: [
|
|
241
|
-
{
|
|
242
|
-
id: '1',
|
|
243
|
-
type: 'text',
|
|
244
|
-
text: `A contact with the phone number ${phoneNumber} could not be created. Make sure you have permission to create contacts in ${platform}.`
|
|
245
|
-
}
|
|
246
|
-
]
|
|
247
|
-
}
|
|
248
|
-
],
|
|
249
|
-
ttl: 5000
|
|
250
|
-
}
|
|
251
|
-
};
|
|
172
|
+
return handleApiError(e, platform, 'createContact', { userId, phoneNumber, newContactName, newContactType, additionalSubmission });
|
|
252
173
|
}
|
|
253
174
|
}
|
|
254
175
|
|
|
@@ -313,28 +234,7 @@ async function findContactWithName({ platform, userId, name }) {
|
|
|
313
234
|
};
|
|
314
235
|
}
|
|
315
236
|
} catch (e) {
|
|
316
|
-
|
|
317
|
-
if (e.response?.status === 429) {
|
|
318
|
-
return {
|
|
319
|
-
successful: false,
|
|
320
|
-
returnMessage: errorMessage.rateLimitErrorMessage({ platform })
|
|
321
|
-
};
|
|
322
|
-
}
|
|
323
|
-
else if (e.response?.status >= 400 && e.response?.status < 410) {
|
|
324
|
-
return {
|
|
325
|
-
successful: false,
|
|
326
|
-
returnMessage: errorMessage.authorizationErrorMessage({ platform }),
|
|
327
|
-
};
|
|
328
|
-
}
|
|
329
|
-
return {
|
|
330
|
-
successful: false,
|
|
331
|
-
returnMessage:
|
|
332
|
-
{
|
|
333
|
-
message: `Error finding contacts`,
|
|
334
|
-
messageType: 'warning',
|
|
335
|
-
ttl: 5000
|
|
336
|
-
}
|
|
337
|
-
};
|
|
237
|
+
return handleApiError(e, platform, 'findContactWithName', { userId, name });
|
|
338
238
|
}
|
|
339
239
|
}
|
|
340
240
|
|