@app-connect/core 1.7.22 → 1.7.24
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/docs/libraries.md +1 -1
- package/handlers/admin.js +7 -4
- package/handlers/auth.js +13 -5
- package/handlers/log.js +217 -109
- package/handlers/plugin.js +183 -1
- package/handlers/user.js +1 -1
- package/index.js +165 -7
- package/lib/authSession.js +44 -12
- package/lib/callLogComposer.js +36 -36
- package/lib/util.js +0 -18
- package/mcp/mcpHandler.js +31 -8
- package/mcp/tools/checkAuthStatus.js +16 -14
- package/mcp/tools/getPublicConnectors.js +11 -1
- package/mcp/tools/getSessionInfo.js +90 -0
- package/mcp/tools/index.js +3 -1
- package/mcp/tools/logout.js +10 -1
- package/models/llmSessionModel.js +3 -0
- package/package.json +1 -1
- package/releaseNotes.json +20 -0
- package/test/handlers/admin.test.js +1 -2
- package/test/handlers/log.test.js +60 -0
- package/test/handlers/plugin.test.js +93 -0
- package/test/lib/callLogComposer.test.js +21 -21
- package/test/lib/util.test.js +1 -332
- package/test/mcp/tools/checkAuthStatus.test.js +82 -0
- package/test/mcp/tools/getSessionInfo.test.js +127 -0
- package/test/mcp/tools/logout.test.js +58 -0
- package/test/routes/managedAuthRoutes.test.js +0 -3
package/docs/libraries.md
CHANGED
|
@@ -74,7 +74,7 @@ It supports:
|
|
|
74
74
|
- session id, subject, duration, result, recording, and timestamp formatting
|
|
75
75
|
- transcript and AI note insertion
|
|
76
76
|
- leg journey formatting
|
|
77
|
-
-
|
|
77
|
+
- ACE transcript, summary, score, bullet summary, and deep link sections
|
|
78
78
|
|
|
79
79
|
### `lib/sharedSMSComposer.js`
|
|
80
80
|
|
package/handlers/admin.js
CHANGED
|
@@ -6,6 +6,7 @@ const { RingCentral } = require('../lib/ringcentral');
|
|
|
6
6
|
const { Connector } = require('../models/dynamo/connectorSchema');
|
|
7
7
|
const logger = require('../lib/logger');
|
|
8
8
|
const { handleDatabaseError } = require('../lib/errorHandler');
|
|
9
|
+
const { getHashValue } = require('../lib/util');
|
|
9
10
|
|
|
10
11
|
const CALL_AGGREGATION_GROUPS = ["Company", "CompanyNumbers", "Users", "Queues", "IVRs", "IVAs", "SharedLines", "UserGroups", "Sites", "Departments"]
|
|
11
12
|
const RC_EXTENSION_ENDPOINT = 'https://platform.ringcentral.com/restapi/v1.0/account/~/extension/~';
|
|
@@ -108,7 +109,8 @@ async function getAdminReport({ rcAccountId, timezone, timeFrom, timeTo, groupBy
|
|
|
108
109
|
clientSecret: process.env.RINGCENTRAL_CLIENT_SECRET,
|
|
109
110
|
redirectUri: `${process.env.APP_SERVER}/ringcentral/oauth/callback`
|
|
110
111
|
});
|
|
111
|
-
|
|
112
|
+
const hashedRcAccountId = getHashValue(rcAccountId, process.env.HASH_KEY);
|
|
113
|
+
let adminConfig = await AdminConfigModel.findByPk(hashedRcAccountId);
|
|
112
114
|
const isTokenExpired = adminConfig.adminTokenExpiry < new Date();
|
|
113
115
|
if (isTokenExpired) {
|
|
114
116
|
const { access_token, refresh_token, expire_time } = await rcSDK.refreshToken({
|
|
@@ -116,7 +118,7 @@ async function getAdminReport({ rcAccountId, timezone, timeFrom, timeTo, groupBy
|
|
|
116
118
|
expires_in: adminConfig.adminTokenExpiry,
|
|
117
119
|
refresh_token_expires_in: adminConfig.adminTokenExpiry
|
|
118
120
|
});
|
|
119
|
-
adminConfig = await AdminConfigModel.update({ adminAccessToken: access_token, adminRefreshToken: refresh_token, adminTokenExpiry: expire_time }, { where: { id:
|
|
121
|
+
adminConfig = await AdminConfigModel.update({ adminAccessToken: access_token, adminRefreshToken: refresh_token, adminTokenExpiry: expire_time }, { where: { id: hashedRcAccountId } });
|
|
120
122
|
}
|
|
121
123
|
const callsAggregationData = await rcSDK.getCallsAggregationData({
|
|
122
124
|
token: { access_token: adminConfig.adminAccessToken, token_type: 'Bearer' },
|
|
@@ -177,7 +179,8 @@ async function getUserReport({ rcAccountId, rcExtensionId, timezone, timeFrom, t
|
|
|
177
179
|
clientSecret: process.env.RINGCENTRAL_CLIENT_SECRET,
|
|
178
180
|
redirectUri: `${process.env.APP_SERVER}/ringcentral/oauth/callback`
|
|
179
181
|
});
|
|
180
|
-
|
|
182
|
+
const hashedRcAccountId = getHashValue(rcAccountId, process.env.HASH_KEY);
|
|
183
|
+
let adminConfig = await AdminConfigModel.findByPk(hashedRcAccountId);
|
|
181
184
|
const isTokenExpired = adminConfig.adminTokenExpiry < new Date();
|
|
182
185
|
if (isTokenExpired) {
|
|
183
186
|
const { access_token, refresh_token, expire_time } = await rcSDK.refreshToken({
|
|
@@ -185,7 +188,7 @@ async function getUserReport({ rcAccountId, rcExtensionId, timezone, timeFrom, t
|
|
|
185
188
|
expires_in: adminConfig.adminTokenExpiry,
|
|
186
189
|
refresh_token_expires_in: adminConfig.adminTokenExpiry
|
|
187
190
|
});
|
|
188
|
-
adminConfig = await AdminConfigModel.update({ adminAccessToken: access_token, adminRefreshToken: refresh_token, adminTokenExpiry: expire_time }, { where: { id:
|
|
191
|
+
adminConfig = await AdminConfigModel.update({ adminAccessToken: access_token, adminRefreshToken: refresh_token, adminTokenExpiry: expire_time }, { where: { id: hashedRcAccountId } });
|
|
189
192
|
}
|
|
190
193
|
const callLogData = await rcSDK.getCallLogData({
|
|
191
194
|
extensionId: rcExtensionId,
|
package/handlers/auth.js
CHANGED
|
@@ -7,6 +7,7 @@ const adminCore = require('./admin');
|
|
|
7
7
|
const { Connector } = require('../models/dynamo/connectorSchema');
|
|
8
8
|
const { handleDatabaseError } = require('../lib/errorHandler');
|
|
9
9
|
const managedAuthCore = require('./managedAuth');
|
|
10
|
+
const { getHashValue } = require('../lib/util');
|
|
10
11
|
|
|
11
12
|
async function onOAuthCallback({ platform, hostname, tokenUrl, query, hashedRcExtensionId, isFromMCP = false }) {
|
|
12
13
|
const callbackUri = query.callbackUri;
|
|
@@ -80,10 +81,16 @@ async function onOAuthCallback({ platform, hostname, tokenUrl, query, hashedRcEx
|
|
|
80
81
|
|
|
81
82
|
async function onApiKeyLogin({ platform, hostname, apiKey, proxyId, rcAccountId, rcExtensionId, connectorId, isPrivate, hashedRcExtensionId, additionalInfo }) {
|
|
82
83
|
const platformModule = connectorRegistry.getConnector(platform);
|
|
83
|
-
let resolvedAdditionalInfo =
|
|
84
|
+
let resolvedAdditionalInfo = {
|
|
85
|
+
...(additionalInfo ?? {})
|
|
86
|
+
};
|
|
87
|
+
if (resolvedAdditionalInfo.apiKey === undefined && apiKey !== undefined) {
|
|
88
|
+
resolvedAdditionalInfo.apiKey = apiKey;
|
|
89
|
+
}
|
|
84
90
|
let resolvedApiKey = apiKey;
|
|
85
|
-
|
|
86
|
-
|
|
91
|
+
let managedFieldDefinitions = [];
|
|
92
|
+
if (rcAccountId) {
|
|
93
|
+
managedFieldDefinitions = await managedAuthCore.getManagedFieldDefinitions({ platform, connectorId, isPrivate });
|
|
87
94
|
const shouldFallbackToManualAuth = managedFieldDefinitions.length > 0
|
|
88
95
|
&& await managedAuthCore.hasManagedAuthLoginFailure({ rcAccountId, platform, rcExtensionId });
|
|
89
96
|
const managedAuthResult = await managedAuthCore.resolveApiKeyLoginFields({
|
|
@@ -93,7 +100,7 @@ async function onApiKeyLogin({ platform, hostname, apiKey, proxyId, rcAccountId,
|
|
|
93
100
|
connectorId,
|
|
94
101
|
isPrivate,
|
|
95
102
|
apiKey,
|
|
96
|
-
additionalInfo,
|
|
103
|
+
additionalInfo: resolvedAdditionalInfo,
|
|
97
104
|
preferSubmittedValuesForManagedFields: shouldFallbackToManualAuth
|
|
98
105
|
});
|
|
99
106
|
resolvedAdditionalInfo = managedAuthResult.resolvedAdditionalInfo;
|
|
@@ -273,8 +280,9 @@ async function onRingcentralOAuthCallback({ code, rcAccountId }) {
|
|
|
273
280
|
redirectUri: `${process.env.APP_SERVER}/ringcentral/oauth/callback`
|
|
274
281
|
});
|
|
275
282
|
const { access_token, refresh_token, expire_time } = await rcSDK.generateToken({ code });
|
|
283
|
+
const hashedRcAccountId = getHashValue(rcAccountId, process.env.HASH_KEY);
|
|
276
284
|
await adminCore.updateAdminRcTokens({
|
|
277
|
-
hashedRcAccountId
|
|
285
|
+
hashedRcAccountId,
|
|
278
286
|
adminAccessToken: access_token,
|
|
279
287
|
adminRefreshToken: refresh_token,
|
|
280
288
|
adminTokenExpiry: expire_time
|
package/handlers/log.js
CHANGED
|
@@ -18,8 +18,32 @@ const logger = require('../lib/logger');
|
|
|
18
18
|
const { handleApiError, handleDatabaseError } = require('../lib/errorHandler');
|
|
19
19
|
const { v4: uuidv4 } = require('uuid');
|
|
20
20
|
const { AccountDataModel } = require('../models/accountDataModel');
|
|
21
|
+
const pluginCore = require('./plugin');
|
|
21
22
|
|
|
22
|
-
|
|
23
|
+
function mergePluginWarnings({ returnMessage, warningMessages }) {
|
|
24
|
+
if (!warningMessages.length) {
|
|
25
|
+
return returnMessage;
|
|
26
|
+
}
|
|
27
|
+
const warningMessage = warningMessages.join(' ');
|
|
28
|
+
if (!returnMessage) {
|
|
29
|
+
return {
|
|
30
|
+
message: warningMessage,
|
|
31
|
+
messageType: 'warning',
|
|
32
|
+
ttl: 5000,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
...returnMessage,
|
|
37
|
+
message: `${returnMessage.message || ''} ${warningMessage}`.trim(),
|
|
38
|
+
messageType: returnMessage.messageType === 'error' ? 'error' : 'warning',
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function getPluginWarningMessage({ pluginId }) {
|
|
43
|
+
return `Plugin ${pluginId} skipped: missing account-level plugin jwtToken. Reinstall or re-register plugin.`;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async function createCallLog({ platform, userId, incomingData, hashedAccountId, isFromSSCL }) {
|
|
23
47
|
try {
|
|
24
48
|
let existingCallLog = null;
|
|
25
49
|
try {
|
|
@@ -122,56 +146,78 @@ async function createCallLog({ jwtToken, platform, userId, incomingData, hashedA
|
|
|
122
146
|
|
|
123
147
|
|
|
124
148
|
const pluginAsyncTaskIds = [];
|
|
149
|
+
const pluginWarnings = [];
|
|
125
150
|
// Plugins
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
break;
|
|
134
|
-
case 'private':
|
|
135
|
-
case 'shared':
|
|
136
|
-
pluginDataResponse = await axios.get(`https://appconnect.labs.ringcentral.com/public-api/connectors/${pluginId}/manifest?access=internal&type=connector&accountId=${user.rcAccountId}`);
|
|
137
|
-
break;
|
|
138
|
-
default:
|
|
139
|
-
throw new Error('Invalid plugin access');
|
|
140
|
-
}
|
|
141
|
-
const pluginData = pluginDataResponse.data;
|
|
142
|
-
const pluginManifest = pluginData.platforms[pluginSetting.value.name];
|
|
143
|
-
let pluginEndpointUrl = pluginManifest.endpointUrl;
|
|
151
|
+
const accountPlugins = await pluginCore.getPluginsFromRcAccountId({ rcAccountId: user.rcAccountId });
|
|
152
|
+
const callPlugins = accountPlugins.filter(plugin => plugin.data.supportedLogTypes.includes('call'));
|
|
153
|
+
for (const plugin of callPlugins) {
|
|
154
|
+
const pluginId = plugin.id;
|
|
155
|
+
const pluginJwtToken = plugin.data.jwtToken;
|
|
156
|
+
const pluginManifest = plugin.data;
|
|
157
|
+
const pluginEndpointUrl = pluginManifest.endpointUrl;
|
|
144
158
|
if (!pluginEndpointUrl) {
|
|
145
159
|
throw new Error('Plugin URL is not set');
|
|
146
160
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
if (pluginEndpointUrl.includes('?')) {
|
|
150
|
-
pluginEndpointUrl += `&jwtToken=${jwtToken}`;
|
|
151
|
-
}
|
|
152
|
-
else {
|
|
153
|
-
pluginEndpointUrl += `?jwtToken=${jwtToken}`;
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
if (pluginSetting.value.isAsync) {
|
|
161
|
+
const userConfig = pluginCore.getPluginConfigFromUserSettings({ userSettings: user.userSettings, pluginId });
|
|
162
|
+
if (plugin.data.isAsync) {
|
|
157
163
|
const asyncTaskId = `${userId}-${uuidv4()}`;
|
|
158
164
|
pluginAsyncTaskIds.push(asyncTaskId);
|
|
159
165
|
await CacheModel.create({
|
|
160
166
|
id: asyncTaskId,
|
|
161
167
|
status: 'initialized',
|
|
162
168
|
userId,
|
|
163
|
-
cacheKey: `pluginTask-${
|
|
169
|
+
cacheKey: `pluginTask-${plugin.data.name}`,
|
|
164
170
|
expiry: moment().add(1, 'hour').toDate()
|
|
165
171
|
});
|
|
166
|
-
|
|
167
|
-
data
|
|
168
|
-
|
|
169
|
-
|
|
172
|
+
try {
|
|
173
|
+
const syncPluginTokenResponse = await axios.post(plugin.data.tokenSyncUrl, {},
|
|
174
|
+
{
|
|
175
|
+
headers: {
|
|
176
|
+
Authorization: `Bearer ${pluginJwtToken}`,
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
)
|
|
180
|
+
const syncedPluginJwtToken = syncPluginTokenResponse?.data?.jwtToken ?? pluginJwtToken;
|
|
181
|
+
axios.post(pluginEndpointUrl, {
|
|
182
|
+
data: incomingData,
|
|
183
|
+
config: userConfig,
|
|
184
|
+
asyncTaskId
|
|
185
|
+
}, {
|
|
186
|
+
headers: {
|
|
187
|
+
Authorization: `Bearer ${syncedPluginJwtToken ?? pluginJwtToken}`,
|
|
188
|
+
},
|
|
189
|
+
});
|
|
190
|
+
if (syncedPluginJwtToken) {
|
|
191
|
+
pluginCore.persistPluginData({
|
|
192
|
+
rcAccountId: user.rcAccountId,
|
|
193
|
+
platformName: platform,
|
|
194
|
+
pluginId,
|
|
195
|
+
jwtToken: syncedPluginJwtToken,
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
catch (error) {
|
|
200
|
+
logger.error('Error syncing plugin JWT token', { stack: error.stack });
|
|
201
|
+
}
|
|
170
202
|
}
|
|
171
203
|
else {
|
|
172
204
|
const processedResultResponse = await axios.post(pluginEndpointUrl, {
|
|
173
|
-
data: incomingData
|
|
205
|
+
data: incomingData,
|
|
206
|
+
config: userConfig,
|
|
207
|
+
}, {
|
|
208
|
+
headers: {
|
|
209
|
+
Authorization: `Bearer ${pluginJwtToken}`,
|
|
210
|
+
},
|
|
174
211
|
});
|
|
212
|
+
const refreshedPluginJwtToken = pluginCore.getRefreshedJwtTokenFromHeaders({ headers: processedResultResponse.headers });
|
|
213
|
+
if (refreshedPluginJwtToken) {
|
|
214
|
+
pluginCore.persistPluginData({
|
|
215
|
+
rcAccountId: user.rcAccountId,
|
|
216
|
+
platformName: platform,
|
|
217
|
+
pluginId,
|
|
218
|
+
jwtToken: refreshedPluginJwtToken,
|
|
219
|
+
});
|
|
220
|
+
}
|
|
175
221
|
// eslint-disable-next-line no-param-reassign
|
|
176
222
|
incomingData = processedResultResponse.data;
|
|
177
223
|
note = incomingData.note;
|
|
@@ -242,7 +288,13 @@ async function createCallLog({ jwtToken, platform, userId, incomingData, hashedA
|
|
|
242
288
|
catch (error) {
|
|
243
289
|
return handleDatabaseError(error, 'Error creating call log');
|
|
244
290
|
}
|
|
245
|
-
return {
|
|
291
|
+
return {
|
|
292
|
+
successful: !!logId,
|
|
293
|
+
logId,
|
|
294
|
+
returnMessage: mergePluginWarnings({ returnMessage, warningMessages: pluginWarnings }),
|
|
295
|
+
extraDataTracking,
|
|
296
|
+
pluginAsyncTaskIds
|
|
297
|
+
};
|
|
246
298
|
}
|
|
247
299
|
} catch (e) {
|
|
248
300
|
return handleApiError(e, platform, 'createCallLog', { userId });
|
|
@@ -348,7 +400,7 @@ async function getCallLog({ userId, sessionIds, platform, requireDetails }) {
|
|
|
348
400
|
}
|
|
349
401
|
}
|
|
350
402
|
|
|
351
|
-
async function updateCallLog({
|
|
403
|
+
async function updateCallLog({ platform, userId, incomingData, hashedAccountId, isFromSSCL }) {
|
|
352
404
|
try {
|
|
353
405
|
let existingCallLog = null;
|
|
354
406
|
try {
|
|
@@ -398,55 +450,78 @@ async function updateCallLog({ jwtToken, platform, userId, incomingData, hashedA
|
|
|
398
450
|
}
|
|
399
451
|
|
|
400
452
|
const pluginAsyncTaskIds = [];
|
|
453
|
+
const pluginWarnings = [];
|
|
401
454
|
// Plugins
|
|
402
|
-
const
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
break;
|
|
410
|
-
case 'private':
|
|
411
|
-
case 'shared':
|
|
412
|
-
pluginDataResponse = await axios.get(`https://appconnect.labs.ringcentral.com/public-api/connectors/${pluginId}/manifest?access=internal&type=connector&accountId=${user.rcAccountId}`);
|
|
413
|
-
break;
|
|
414
|
-
default:
|
|
415
|
-
throw new Error('Invalid plugin access');
|
|
416
|
-
}
|
|
417
|
-
const pluginData = pluginDataResponse.data;
|
|
418
|
-
const pluginManifest = pluginData.platforms[pluginSetting.value.name];
|
|
419
|
-
let pluginEndpointUrl = pluginManifest.endpointUrl;
|
|
455
|
+
const accountPlugins = await pluginCore.getPluginsFromRcAccountId({ rcAccountId: user.rcAccountId });
|
|
456
|
+
const callPlugins = accountPlugins.filter(plugin => plugin.data.supportedLogTypes.includes('call'));
|
|
457
|
+
for (const plugin of callPlugins) {
|
|
458
|
+
const pluginId = plugin.id;
|
|
459
|
+
const pluginJwtToken = plugin.data.jwtToken;
|
|
460
|
+
const pluginManifest = plugin.data;
|
|
461
|
+
const pluginEndpointUrl = pluginManifest.endpointUrl;
|
|
420
462
|
if (!pluginEndpointUrl) {
|
|
421
463
|
throw new Error('Plugin URL is not set');
|
|
422
464
|
}
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
pluginEndpointUrl += `&jwtToken=${jwtToken}`;
|
|
426
|
-
}
|
|
427
|
-
else {
|
|
428
|
-
pluginEndpointUrl += `?jwtToken=${jwtToken}`;
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
if (pluginSetting.value.isAsync) {
|
|
465
|
+
const userConfig = pluginCore.getPluginConfigFromUserSettings({ userSettings: user.userSettings, pluginId });
|
|
466
|
+
if (plugin.data.isAsync) {
|
|
432
467
|
const asyncTaskId = `${userId}-${uuidv4()}`;
|
|
433
468
|
pluginAsyncTaskIds.push(asyncTaskId);
|
|
434
469
|
await CacheModel.create({
|
|
435
470
|
id: asyncTaskId,
|
|
436
471
|
status: 'initialized',
|
|
437
472
|
userId,
|
|
438
|
-
cacheKey: `pluginTask-${
|
|
473
|
+
cacheKey: `pluginTask-${plugin.data.name}`,
|
|
439
474
|
expiry: moment().add(1, 'hour').toDate()
|
|
440
475
|
});
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
476
|
+
try {
|
|
477
|
+
const syncPluginTokenResponse = await axios.post(plugin.data.tokenSyncUrl, {},
|
|
478
|
+
{
|
|
479
|
+
headers: {
|
|
480
|
+
Authorization: `Bearer ${pluginJwtToken}`,
|
|
481
|
+
},
|
|
482
|
+
}
|
|
483
|
+
);
|
|
484
|
+
const syncedPluginJwtToken = pluginCore.getRefreshedJwtTokenFromHeaders({ headers: syncPluginTokenResponse.headers });
|
|
485
|
+
axios.post(pluginEndpointUrl, {
|
|
486
|
+
data: { logInfo: incomingData },
|
|
487
|
+
config: userConfig,
|
|
488
|
+
asyncTaskId
|
|
489
|
+
}, {
|
|
490
|
+
headers: {
|
|
491
|
+
Authorization: `Bearer ${syncedPluginJwtToken ?? pluginJwtToken}`,
|
|
492
|
+
},
|
|
493
|
+
});
|
|
494
|
+
if (syncedPluginJwtToken) {
|
|
495
|
+
pluginCore.persistPluginData({
|
|
496
|
+
rcAccountId: user.rcAccountId,
|
|
497
|
+
platformName: platform,
|
|
498
|
+
pluginId,
|
|
499
|
+
jwtToken: syncedPluginJwtToken,
|
|
500
|
+
});
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
catch (error) {
|
|
504
|
+
logger.error('Error syncing plugin JWT token', { stack: error.stack });
|
|
505
|
+
}
|
|
445
506
|
}
|
|
446
507
|
else {
|
|
447
508
|
const processedResultResponse = await axios.post(pluginEndpointUrl, {
|
|
448
|
-
data: incomingData
|
|
509
|
+
data: incomingData,
|
|
510
|
+
config: userConfig
|
|
511
|
+
}, {
|
|
512
|
+
headers: {
|
|
513
|
+
Authorization: `Bearer ${pluginJwtToken}`,
|
|
514
|
+
},
|
|
449
515
|
});
|
|
516
|
+
const refreshedPluginJwtToken = pluginCore.getRefreshedJwtTokenFromHeaders({ headers: processedResultResponse.headers });
|
|
517
|
+
if (refreshedPluginJwtToken) {
|
|
518
|
+
pluginCore.persistPluginData({
|
|
519
|
+
rcAccountId: user.rcAccountId,
|
|
520
|
+
platformName: platform,
|
|
521
|
+
pluginId,
|
|
522
|
+
jwtToken: refreshedPluginJwtToken,
|
|
523
|
+
});
|
|
524
|
+
}
|
|
450
525
|
// eslint-disable-next-line no-param-reassign
|
|
451
526
|
incomingData = processedResultResponse.data;
|
|
452
527
|
}
|
|
@@ -534,7 +609,14 @@ async function updateCallLog({ jwtToken, platform, userId, incomingData, hashedA
|
|
|
534
609
|
isFromSSCL,
|
|
535
610
|
proxyConfig,
|
|
536
611
|
});
|
|
537
|
-
return {
|
|
612
|
+
return {
|
|
613
|
+
successful: true,
|
|
614
|
+
logId: existingCallLog.thirdPartyLogId,
|
|
615
|
+
updatedNote,
|
|
616
|
+
returnMessage: mergePluginWarnings({ returnMessage, warningMessages: pluginWarnings }),
|
|
617
|
+
extraDataTracking,
|
|
618
|
+
pluginAsyncTaskIds
|
|
619
|
+
};
|
|
538
620
|
}
|
|
539
621
|
return { successful: false };
|
|
540
622
|
} catch (e) {
|
|
@@ -632,59 +714,82 @@ async function createMessageLog({ platform, userId, incomingData }) {
|
|
|
632
714
|
const isSharedSMS = !!ownerName;
|
|
633
715
|
|
|
634
716
|
const pluginAsyncTaskIds = [];
|
|
717
|
+
const pluginWarnings = [];
|
|
635
718
|
// Plugins
|
|
636
719
|
const isSMS = incomingData.logInfo.messages.some(m => m.type === 'SMS');
|
|
637
720
|
const isFax = incomingData.logInfo.messages.some(m => m.type === 'Fax');
|
|
638
|
-
const
|
|
639
|
-
const
|
|
721
|
+
const accountPlugins = await pluginCore.getPluginsFromRcAccountId({ rcAccountId: user.rcAccountId });
|
|
722
|
+
const smsPlugins = isSMS ? accountPlugins.filter(plugin => plugin.data.supportedLogTypes.includes('sms')) : [];
|
|
723
|
+
const faxPlugins = isFax ? accountPlugins.filter(plugin => plugin.data.supportedLogTypes.includes('fax')) : [];
|
|
640
724
|
const plugins = [...smsPlugins, ...faxPlugins];
|
|
641
|
-
for (const
|
|
642
|
-
const pluginId =
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
pluginDataResponse = await axios.get(`https://appconnect.labs.ringcentral.com/public-api/connectors/${pluginId}/manifest?type=plugin`);
|
|
647
|
-
break;
|
|
648
|
-
case 'private':
|
|
649
|
-
case 'shared':
|
|
650
|
-
pluginDataResponse = await axios.get(`https://appconnect.labs.ringcentral.com/public-api/connectors/${pluginId}/manifest?access=internal&type=connector&accountId=${user.rcAccountId}`);
|
|
651
|
-
break;
|
|
652
|
-
default:
|
|
653
|
-
throw new Error('Invalid plugin access');
|
|
654
|
-
}
|
|
655
|
-
const pluginData = pluginDataResponse.data;
|
|
656
|
-
const pluginManifest = pluginData.platforms[pluginSetting.value.name];
|
|
657
|
-
let pluginEndpointUrl = pluginManifest.endpointUrl;
|
|
725
|
+
for (const plugin of plugins) {
|
|
726
|
+
const pluginId = plugin.id;
|
|
727
|
+
const pluginJwtToken = plugin.data.jwtToken;
|
|
728
|
+
const pluginManifest = plugin.data;
|
|
729
|
+
const pluginEndpointUrl = pluginManifest.endpointUrl;
|
|
658
730
|
if (!pluginEndpointUrl) {
|
|
659
731
|
throw new Error('Plugin URL is not set');
|
|
660
732
|
}
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
pluginEndpointUrl += `&jwtToken=${jwtToken}`;
|
|
664
|
-
}
|
|
665
|
-
else {
|
|
666
|
-
pluginEndpointUrl += `?jwtToken=${jwtToken}`;
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
if (pluginSetting.value.isAsync) {
|
|
733
|
+
const userConfig = pluginCore.getPluginConfigFromUserSettings({ userSettings: user.userSettings, pluginId });
|
|
734
|
+
if (plugin.data.isAsync) {
|
|
670
735
|
const asyncTaskId = `${userId}-${uuidv4()}`;
|
|
671
736
|
pluginAsyncTaskIds.push(asyncTaskId);
|
|
672
737
|
await CacheModel.create({
|
|
673
738
|
id: asyncTaskId,
|
|
674
739
|
status: 'initialized',
|
|
675
740
|
userId,
|
|
676
|
-
cacheKey: `pluginTask-${
|
|
741
|
+
cacheKey: `pluginTask-${plugin.data.name}`,
|
|
677
742
|
expiry: moment().add(1, 'hour').toDate()
|
|
678
743
|
});
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
744
|
+
try {
|
|
745
|
+
const syncPluginTokenResponse = await axios.post(plugin.data.tokenSyncUrl, {},
|
|
746
|
+
{
|
|
747
|
+
headers: {
|
|
748
|
+
Authorization: `Bearer ${pluginJwtToken}`,
|
|
749
|
+
},
|
|
750
|
+
}
|
|
751
|
+
);
|
|
752
|
+
const syncedPluginJwtToken = pluginCore.getRefreshedJwtTokenFromHeaders({ headers: syncPluginTokenResponse.headers });
|
|
753
|
+
axios.post(pluginEndpointUrl, {
|
|
754
|
+
data: { logInfo: incomingData },
|
|
755
|
+
config: userConfig,
|
|
756
|
+
asyncTaskId
|
|
757
|
+
}, {
|
|
758
|
+
headers: {
|
|
759
|
+
Authorization: `Bearer ${syncedPluginJwtToken ?? pluginJwtToken}`,
|
|
760
|
+
},
|
|
761
|
+
});
|
|
762
|
+
if (syncedPluginJwtToken) {
|
|
763
|
+
pluginCore.persistPluginData({
|
|
764
|
+
rcAccountId: user.rcAccountId,
|
|
765
|
+
platformName: platform,
|
|
766
|
+
pluginId,
|
|
767
|
+
jwtToken: syncedPluginJwtToken,
|
|
768
|
+
});
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
catch (error) {
|
|
772
|
+
logger.error('Error syncing plugin JWT token', { stack: error.stack });
|
|
773
|
+
}
|
|
683
774
|
}
|
|
684
775
|
else {
|
|
685
776
|
const processedResultResponse = await axios.post(pluginEndpointUrl, {
|
|
686
|
-
data: incomingData
|
|
777
|
+
data: incomingData,
|
|
778
|
+
config: userConfig,
|
|
779
|
+
}, {
|
|
780
|
+
headers: {
|
|
781
|
+
Authorization: `Bearer ${pluginJwtToken}`,
|
|
782
|
+
},
|
|
687
783
|
});
|
|
784
|
+
const refreshedPluginJwtToken = pluginCore.getRefreshedJwtTokenFromHeaders({ headers: processedResultResponse.headers });
|
|
785
|
+
if (refreshedPluginJwtToken) {
|
|
786
|
+
pluginCore.persistPluginData({
|
|
787
|
+
rcAccountId: user.rcAccountId,
|
|
788
|
+
platformName: platform,
|
|
789
|
+
pluginId,
|
|
790
|
+
jwtToken: refreshedPluginJwtToken,
|
|
791
|
+
});
|
|
792
|
+
}
|
|
688
793
|
// eslint-disable-next-line no-param-reassign
|
|
689
794
|
incomingData = processedResultResponse.data;
|
|
690
795
|
}
|
|
@@ -731,7 +836,6 @@ async function createMessageLog({ platform, userId, incomingData }) {
|
|
|
731
836
|
conversationLogId: incomingData.logInfo.conversationLogId
|
|
732
837
|
}
|
|
733
838
|
});
|
|
734
|
-
const entities = incomingData.logInfo.entities;
|
|
735
839
|
const sharedSMSLogContent = composeSharedSMSLog({ logFormat: platformModule.getLogFormatType(platform, proxyConfig), conversation: incomingData.logInfo, contactName: contactInfo.name, timezoneOffset: user.timezoneOffset });
|
|
736
840
|
if (existingMessageLog) {
|
|
737
841
|
const updateMessageResult = await platformModule.updateMessageLog({ user, contactInfo, sharedSMSLogContent, existingMessageLog: existingMessageLog, authHeader, additionalSubmission, proxyConfig });
|
|
@@ -739,7 +843,6 @@ async function createMessageLog({ platform, userId, incomingData }) {
|
|
|
739
843
|
}
|
|
740
844
|
else {
|
|
741
845
|
const createMessageLogResult = await platformModule.createMessageLog({ user, contactInfo, sharedSMSLogContent, authHeader, additionalSubmission, proxyConfig });
|
|
742
|
-
const crmLogId = createMessageLogResult.logId;
|
|
743
846
|
returnMessage = createMessageLogResult?.returnMessage;
|
|
744
847
|
extraDataTracking = createMessageLogResult.extraDataTracking;
|
|
745
848
|
if (createMessageLogResult.logId) {
|
|
@@ -841,7 +944,12 @@ async function createMessageLog({ platform, userId, incomingData }) {
|
|
|
841
944
|
}
|
|
842
945
|
}
|
|
843
946
|
}
|
|
844
|
-
return {
|
|
947
|
+
return {
|
|
948
|
+
successful: true,
|
|
949
|
+
logIds,
|
|
950
|
+
returnMessage: mergePluginWarnings({ returnMessage, warningMessages: pluginWarnings }),
|
|
951
|
+
extraDataTracking
|
|
952
|
+
};
|
|
845
953
|
}
|
|
846
954
|
catch (e) {
|
|
847
955
|
return handleApiError(e, platform, 'createMessageLog', { userId });
|
|
@@ -862,4 +970,4 @@ exports.createCallLog = createCallLog;
|
|
|
862
970
|
exports.updateCallLog = updateCallLog;
|
|
863
971
|
exports.createMessageLog = createMessageLog;
|
|
864
972
|
exports.getCallLog = getCallLog;
|
|
865
|
-
exports.saveNoteCache = saveNoteCache;
|
|
973
|
+
exports.saveNoteCache = saveNoteCache;
|