@app-connect/core 1.7.21 → 1.7.23
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/README.md +8 -1
- package/connector/developerPortal.js +4 -4
- package/docs/README.md +50 -0
- package/docs/architecture.md +93 -0
- package/docs/connectors.md +117 -0
- package/docs/handlers.md +125 -0
- package/docs/libraries.md +101 -0
- package/docs/models.md +144 -0
- package/docs/routes.md +115 -0
- package/docs/tests.md +73 -0
- package/handlers/admin.js +22 -2
- package/handlers/auth.js +57 -10
- package/handlers/log.js +217 -109
- package/handlers/managedAuth.js +446 -0
- package/handlers/plugin.js +183 -1
- package/handlers/user.js +1 -1
- package/index.js +410 -35
- package/lib/callLogComposer.js +36 -36
- package/lib/jwt.js +1 -1
- package/lib/util.js +0 -18
- package/mcp/tools/createCallLog.js +5 -1
- package/mcp/tools/createContact.js +5 -1
- package/mcp/tools/createMessageLog.js +5 -1
- package/mcp/tools/findContactByName.js +5 -1
- package/mcp/tools/findContactByPhone.js +6 -2
- package/mcp/tools/getCallLog.js +5 -1
- package/mcp/tools/rcGetCallLogs.js +6 -2
- package/mcp/tools/updateCallLog.js +5 -1
- package/mcp/ui/App/lib/developerPortal.ts +1 -1
- package/package.json +72 -72
- package/releaseNotes.json +16 -0
- package/test/handlers/admin.test.js +33 -0
- package/test/handlers/auth.test.js +402 -6
- package/test/handlers/log.test.js +60 -0
- package/test/handlers/managedAuth.test.js +458 -0
- package/test/handlers/plugin.test.js +93 -0
- package/test/index.test.js +105 -0
- package/test/lib/callLogComposer.test.js +21 -21
- package/test/lib/jwt.test.js +15 -0
- package/test/lib/util.test.js +1 -332
- package/test/mcp/tools/createCallLog.test.js +11 -0
- package/test/mcp/tools/createContact.test.js +58 -0
- package/test/mcp/tools/createMessageLog.test.js +15 -0
- package/test/mcp/tools/findContactByName.test.js +12 -0
- package/test/mcp/tools/findContactByPhone.test.js +12 -0
- package/test/mcp/tools/getCallLog.test.js +12 -0
- package/test/mcp/tools/rcGetCallLogs.test.js +56 -0
- package/test/mcp/tools/updateCallLog.test.js +14 -0
- package/test/routes/managedAuthRoutes.test.js +129 -0
- package/test/setup.js +2 -0
package/lib/callLogComposer.js
CHANGED
|
@@ -702,27 +702,27 @@ function upsertRingSenseTranscript({ body, transcript, logFormat }) {
|
|
|
702
702
|
switch (logFormat) {
|
|
703
703
|
case LOG_DETAILS_FORMAT_TYPE.HTML:
|
|
704
704
|
const formattedTranscript = clearedTranscript.replace(/(?:\r\n|\r|\n)/g, '<br>');
|
|
705
|
-
transcriptRegex = /<div><b>
|
|
705
|
+
transcriptRegex = /<div><b>ACE transcript<\/b><br>(.+?)<\/div>/;
|
|
706
706
|
if (transcriptRegex.test(result)) {
|
|
707
|
-
result = result.replace(transcriptRegex, `<div><b>
|
|
707
|
+
result = result.replace(transcriptRegex, `<div><b>ACE transcript</b><br>${formattedTranscript}</div>`);
|
|
708
708
|
} else {
|
|
709
|
-
result += `<div><b>
|
|
709
|
+
result += `<div><b>ACE transcript</b><br>${formattedTranscript}</div>`;
|
|
710
710
|
}
|
|
711
711
|
break;
|
|
712
712
|
case LOG_DETAILS_FORMAT_TYPE.MARKDOWN:
|
|
713
|
-
transcriptRegex = /###
|
|
713
|
+
transcriptRegex = /### ACE transcript\n([\s\S]*?)(?=\n### |\n$|$)/;
|
|
714
714
|
if (transcriptRegex.test(result)) {
|
|
715
|
-
result = result.replace(transcriptRegex, `###
|
|
715
|
+
result = result.replace(transcriptRegex, `### ACE transcript\n${clearedTranscript}\n`);
|
|
716
716
|
} else {
|
|
717
|
-
result += `###
|
|
717
|
+
result += `### ACE transcript\n${clearedTranscript}\n`;
|
|
718
718
|
}
|
|
719
719
|
break;
|
|
720
720
|
case LOG_DETAILS_FORMAT_TYPE.PLAIN_TEXT:
|
|
721
|
-
transcriptRegex = /-
|
|
721
|
+
transcriptRegex = /- ACE transcript:([\s\S]*?)--- END/;
|
|
722
722
|
if (transcriptRegex.test(result)) {
|
|
723
|
-
result = result.replace(transcriptRegex, `-
|
|
723
|
+
result = result.replace(transcriptRegex, `- ACE transcript:\n${clearedTranscript}\n--- END`);
|
|
724
724
|
} else {
|
|
725
|
-
result += `\n-
|
|
725
|
+
result += `\n- ACE transcript:\n${clearedTranscript}\n--- END\n`;
|
|
726
726
|
}
|
|
727
727
|
break;
|
|
728
728
|
}
|
|
@@ -739,28 +739,28 @@ function upsertRingSenseSummary({ body, summary, logFormat }) {
|
|
|
739
739
|
|
|
740
740
|
switch (logFormat) {
|
|
741
741
|
case LOG_DETAILS_FORMAT_TYPE.HTML:
|
|
742
|
-
summaryRegex = /<div><b>
|
|
742
|
+
summaryRegex = /<div><b>ACE summary<\/b><br>(.+?)<\/div>/;
|
|
743
743
|
const formattedSummary = clearedSummary.replace(/(?:\r\n|\r|\n)/g, '<br>');
|
|
744
744
|
if (summaryRegex.test(result)) {
|
|
745
|
-
result = result.replace(summaryRegex, `<div><b>
|
|
745
|
+
result = result.replace(summaryRegex, `<div><b>ACE summary</b><br>${formattedSummary}</div>`);
|
|
746
746
|
} else {
|
|
747
|
-
result += `<div><b>
|
|
747
|
+
result += `<div><b>ACE summary</b><br>${formattedSummary}</div>`;
|
|
748
748
|
}
|
|
749
749
|
break;
|
|
750
750
|
case LOG_DETAILS_FORMAT_TYPE.MARKDOWN:
|
|
751
|
-
summaryRegex = /###
|
|
751
|
+
summaryRegex = /### ACE summary\n([\s\S]*?)(?=\n### |\n$|$)/;
|
|
752
752
|
if (summaryRegex.test(result)) {
|
|
753
|
-
result = result.replace(summaryRegex, `###
|
|
753
|
+
result = result.replace(summaryRegex, `### ACE summary\n${summary}\n`);
|
|
754
754
|
} else {
|
|
755
|
-
result += `###
|
|
755
|
+
result += `### ACE summary\n${summary}\n`;
|
|
756
756
|
}
|
|
757
757
|
break;
|
|
758
758
|
case LOG_DETAILS_FORMAT_TYPE.PLAIN_TEXT:
|
|
759
|
-
summaryRegex = /-
|
|
759
|
+
summaryRegex = /- ACE summary:([\s\S]*?)--- END/;
|
|
760
760
|
if (summaryRegex.test(result)) {
|
|
761
|
-
result = result.replace(summaryRegex, `-
|
|
761
|
+
result = result.replace(summaryRegex, `- ACE summary:\n${summary}\n--- END`);
|
|
762
762
|
} else {
|
|
763
|
-
result += `\n-
|
|
763
|
+
result += `\n- ACE summary:\n${summary}\n--- END\n`;
|
|
764
764
|
}
|
|
765
765
|
break;
|
|
766
766
|
}
|
|
@@ -811,28 +811,28 @@ function upsertRingSenseBulletedSummary({ body, summary, logFormat }) {
|
|
|
811
811
|
|
|
812
812
|
switch (logFormat) {
|
|
813
813
|
case LOG_DETAILS_FORMAT_TYPE.HTML:
|
|
814
|
-
summaryRegex = /<div><b>
|
|
814
|
+
summaryRegex = /<div><b>ACE bulleted summary<\/b><br>(.+?)<\/div>/;
|
|
815
815
|
const formattedSummary = clearedSummary.replace(/(?:\r\n|\r|\n)/g, '<br>');
|
|
816
816
|
if (summaryRegex.test(result)) {
|
|
817
|
-
result = result.replace(summaryRegex, `<div><b>
|
|
817
|
+
result = result.replace(summaryRegex, `<div><b>ACE bulleted summary</b><br>${formattedSummary}</div>`);
|
|
818
818
|
} else {
|
|
819
|
-
result += `<div><b>
|
|
819
|
+
result += `<div><b>ACE bulleted summary</b><br>${formattedSummary}</div>`;
|
|
820
820
|
}
|
|
821
821
|
break;
|
|
822
822
|
case LOG_DETAILS_FORMAT_TYPE.MARKDOWN:
|
|
823
|
-
summaryRegex = /###
|
|
823
|
+
summaryRegex = /### ACE bulleted summary\n([\s\S]*?)(?=\n### |\n$|$)/;
|
|
824
824
|
if (summaryRegex.test(result)) {
|
|
825
|
-
result = result.replace(summaryRegex, `###
|
|
825
|
+
result = result.replace(summaryRegex, `### ACE bulleted summary\n${summary}\n`);
|
|
826
826
|
} else {
|
|
827
|
-
result += `###
|
|
827
|
+
result += `### ACE bulleted summary\n${summary}\n`;
|
|
828
828
|
}
|
|
829
829
|
break;
|
|
830
830
|
case LOG_DETAILS_FORMAT_TYPE.PLAIN_TEXT:
|
|
831
|
-
summaryRegex = /-
|
|
831
|
+
summaryRegex = /- ACE bulleted summary:\s*([^<\n]+)(?=\n|$)/i;
|
|
832
832
|
if (summaryRegex.test(result)) {
|
|
833
|
-
result = result.replace(summaryRegex, `-
|
|
833
|
+
result = result.replace(summaryRegex, `- ACE bulleted summary:\n${summary}\n--- END`);
|
|
834
834
|
} else {
|
|
835
|
-
result += `\n-
|
|
835
|
+
result += `\n- ACE bulleted summary:\n${summary}\n--- END\n`;
|
|
836
836
|
}
|
|
837
837
|
break;
|
|
838
838
|
}
|
|
@@ -847,27 +847,27 @@ function upsertRingSenseLink({ body, link, logFormat }) {
|
|
|
847
847
|
|
|
848
848
|
switch (logFormat) {
|
|
849
849
|
case LOG_DETAILS_FORMAT_TYPE.HTML:
|
|
850
|
-
linkRegex = /(?:<li>)?<b>
|
|
850
|
+
linkRegex = /(?:<li>)?<b>ACE recording link<\/b>:\s*(?:<a[^>]*>[^<]*<\/a>|[^<]+)(?:<\/li>|(?=<|$))/i;
|
|
851
851
|
if (linkRegex.test(result)) {
|
|
852
|
-
result = result.replace(linkRegex, `<li><b>
|
|
852
|
+
result = result.replace(linkRegex, `<li><b>ACE recording link</b>: <a target="_blank" href="${link}">open</a></li>`);
|
|
853
853
|
} else {
|
|
854
|
-
result += `<li><b>
|
|
854
|
+
result += `<li><b>ACE recording link</b>: <a target="_blank" href="${link}">open</a></li>`;
|
|
855
855
|
}
|
|
856
856
|
break;
|
|
857
857
|
case LOG_DETAILS_FORMAT_TYPE.MARKDOWN:
|
|
858
|
-
linkRegex = /\*\*
|
|
858
|
+
linkRegex = /\*\*ACE recording link\*\*:\s*([^<\n]+)(?=\n|$)/i;
|
|
859
859
|
if (linkRegex.test(result)) {
|
|
860
|
-
result = result.replace(linkRegex, `**
|
|
860
|
+
result = result.replace(linkRegex, `**ACE recording link**: ${link}\n`);
|
|
861
861
|
} else {
|
|
862
|
-
result += `**
|
|
862
|
+
result += `**ACE recording link**: ${link}\n`;
|
|
863
863
|
}
|
|
864
864
|
break;
|
|
865
865
|
case LOG_DETAILS_FORMAT_TYPE.PLAIN_TEXT:
|
|
866
|
-
linkRegex = /-
|
|
866
|
+
linkRegex = /- ACE recording link:\s*([^<\n]+)(?=\n|$)/i;
|
|
867
867
|
if (linkRegex.test(result)) {
|
|
868
|
-
result = result.replace(linkRegex, `-
|
|
868
|
+
result = result.replace(linkRegex, `- ACE recording link: ${link}`);
|
|
869
869
|
} else {
|
|
870
|
-
result += `-
|
|
870
|
+
result += `- ACE recording link: ${link}\n`;
|
|
871
871
|
}
|
|
872
872
|
break;
|
|
873
873
|
}
|
package/lib/jwt.js
CHANGED
|
@@ -2,7 +2,7 @@ const { sign, verify } = require('jsonwebtoken');
|
|
|
2
2
|
const logger = require('./logger');
|
|
3
3
|
|
|
4
4
|
function generateJwt(data) {
|
|
5
|
-
return sign(data, process.env.APP_SERVER_SECRET_KEY, { expiresIn: '
|
|
5
|
+
return sign(data, process.env.APP_SERVER_SECRET_KEY, { expiresIn: '2w' })
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
function decodeJwt(token) {
|
package/lib/util.js
CHANGED
|
@@ -60,26 +60,8 @@ function getMediaReaderLinkByPlatformMediaLink(platformMediaLink) {
|
|
|
60
60
|
return `https://ringcentral.github.io/ringcentral-media-reader/?media=${encodedPlatformMediaLink}`;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
function getPluginsFromUserSettings({ userSettings, logType }) {
|
|
64
|
-
const result = [];
|
|
65
|
-
if (!userSettings) {
|
|
66
|
-
return result;
|
|
67
|
-
}
|
|
68
|
-
for (const userSettingKey in userSettings) {
|
|
69
|
-
if (!userSettingKey.startsWith('plugin_')) {
|
|
70
|
-
continue;
|
|
71
|
-
}
|
|
72
|
-
const pluginUserSetting = userSettings[userSettingKey];
|
|
73
|
-
if (pluginUserSetting.value.logTypes.includes(logType)) {
|
|
74
|
-
result.push({ id: userSettingKey.replace('plugin_', ''), value: pluginUserSetting.value });
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
return result;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
63
|
exports.getTimeZone = getTimeZone;
|
|
81
64
|
exports.getHashValue = getHashValue;
|
|
82
65
|
exports.secondsToHoursMinutesSeconds = secondsToHoursMinutesSeconds;
|
|
83
66
|
exports.getMostRecentDate = getMostRecentDate;
|
|
84
67
|
exports.getMediaReaderLinkByPlatformMediaLink = getMediaReaderLinkByPlatformMediaLink;
|
|
85
|
-
exports.getPluginsFromUserSettings = getPluginsFromUserSettings;
|
|
@@ -220,7 +220,11 @@ async function execute(args) {
|
|
|
220
220
|
}
|
|
221
221
|
|
|
222
222
|
// Decode JWT to get userId and platform
|
|
223
|
-
const
|
|
223
|
+
const decodedToken = jwt.decodeJwt(jwtToken);
|
|
224
|
+
if (!decodedToken) {
|
|
225
|
+
throw new Error('Invalid JWT token');
|
|
226
|
+
}
|
|
227
|
+
const { id: userId, platform } = decodedToken;
|
|
224
228
|
|
|
225
229
|
if (!userId) {
|
|
226
230
|
throw new Error('Invalid JWT token: userId not found');
|
|
@@ -57,7 +57,11 @@ async function execute(args) {
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
// Decode JWT to get userId and platform
|
|
60
|
-
const
|
|
60
|
+
const decodedToken = jwt.decodeJwt(jwtToken);
|
|
61
|
+
if (!decodedToken) {
|
|
62
|
+
throw new Error('Invalid JWT token');
|
|
63
|
+
}
|
|
64
|
+
const { id: userId, platform } = decodedToken;
|
|
61
65
|
|
|
62
66
|
if (!userId) {
|
|
63
67
|
throw new Error('Invalid JWT token: userId not found');
|
|
@@ -228,7 +228,11 @@ async function execute(args) {
|
|
|
228
228
|
}
|
|
229
229
|
|
|
230
230
|
// Decode JWT to get userId and platform
|
|
231
|
-
const
|
|
231
|
+
const decodedToken = jwt.decodeJwt(jwtToken);
|
|
232
|
+
if (!decodedToken) {
|
|
233
|
+
throw new Error('Invalid JWT token');
|
|
234
|
+
}
|
|
235
|
+
const { id: userId, platform } = decodedToken;
|
|
232
236
|
|
|
233
237
|
if (!userId) {
|
|
234
238
|
throw new Error('Invalid JWT token: userId not found');
|
|
@@ -42,7 +42,11 @@ async function execute(args) {
|
|
|
42
42
|
throw new Error('Not authenticated. Please connect to your CRM first.');
|
|
43
43
|
}
|
|
44
44
|
// Decode JWT to get userId and platform
|
|
45
|
-
const
|
|
45
|
+
const decodedToken = jwt.decodeJwt(jwtToken);
|
|
46
|
+
if (!decodedToken) {
|
|
47
|
+
throw new Error('Invalid JWT token');
|
|
48
|
+
}
|
|
49
|
+
const { id: userId, platform } = decodedToken;
|
|
46
50
|
|
|
47
51
|
if (!userId) {
|
|
48
52
|
throw new Error('Invalid JWT token: userId not found');
|
|
@@ -51,7 +51,11 @@ async function execute(args) {
|
|
|
51
51
|
const { jwtToken, phoneNumber, overridingFormat, isExtension } = args;
|
|
52
52
|
|
|
53
53
|
// Decode JWT to get userId and platform
|
|
54
|
-
const
|
|
54
|
+
const decodedToken = jwt.decodeJwt(jwtToken);
|
|
55
|
+
if (!decodedToken) {
|
|
56
|
+
throw new Error('Invalid JWT token');
|
|
57
|
+
}
|
|
58
|
+
const { id: userId, platform } = decodedToken;
|
|
55
59
|
|
|
56
60
|
if (!userId) {
|
|
57
61
|
throw new Error('Invalid JWT token: userId not found');
|
|
@@ -94,4 +98,4 @@ async function execute(args) {
|
|
|
94
98
|
}
|
|
95
99
|
|
|
96
100
|
exports.definition = toolDefinition;
|
|
97
|
-
exports.execute = execute;
|
|
101
|
+
exports.execute = execute;
|
package/mcp/tools/getCallLog.js
CHANGED
|
@@ -45,7 +45,11 @@ async function execute(args) {
|
|
|
45
45
|
const { jwtToken, sessionIds, requireDetails = false } = args;
|
|
46
46
|
|
|
47
47
|
// Decode JWT to get userId and platform
|
|
48
|
-
const
|
|
48
|
+
const decodedToken = jwt.decodeJwt(jwtToken);
|
|
49
|
+
if (!decodedToken) {
|
|
50
|
+
throw new Error('Invalid JWT token');
|
|
51
|
+
}
|
|
52
|
+
const { id: userId, platform } = decodedToken;
|
|
49
53
|
|
|
50
54
|
if (!userId) {
|
|
51
55
|
throw new Error('Invalid JWT token: userId not found');
|
|
@@ -32,7 +32,11 @@ async function execute(args) {
|
|
|
32
32
|
if (!rcAccessToken) {
|
|
33
33
|
throw new Error('RingCentral access token not found');
|
|
34
34
|
}
|
|
35
|
-
const
|
|
35
|
+
const decodedToken = jwt.decodeJwt(jwtToken);
|
|
36
|
+
if (!decodedToken) {
|
|
37
|
+
throw new Error('Invalid JWT token');
|
|
38
|
+
}
|
|
39
|
+
const { id: userId } = decodedToken;
|
|
36
40
|
if (!userId) {
|
|
37
41
|
throw new Error('Invalid JWT token: userId not found');
|
|
38
42
|
}
|
|
@@ -58,4 +62,4 @@ async function execute(args) {
|
|
|
58
62
|
}
|
|
59
63
|
|
|
60
64
|
exports.definition = toolDefinition;
|
|
61
|
-
exports.execute = execute;
|
|
65
|
+
exports.execute = execute;
|
|
@@ -59,7 +59,11 @@ async function execute(args) {
|
|
|
59
59
|
const { jwtToken, incomingData } = args;
|
|
60
60
|
|
|
61
61
|
// Decode JWT to get userId and platform
|
|
62
|
-
const
|
|
62
|
+
const decodedToken = jwt.decodeJwt(jwtToken);
|
|
63
|
+
if (!decodedToken) {
|
|
64
|
+
throw new Error('Invalid JWT token');
|
|
65
|
+
}
|
|
66
|
+
const { id: userId, platform } = decodedToken;
|
|
63
67
|
|
|
64
68
|
if (!userId) {
|
|
65
69
|
throw new Error('Invalid JWT token: userId not found');
|
|
@@ -90,7 +90,7 @@ export async function fetchManifest(
|
|
|
90
90
|
dbg.info('fetchManifest: connectorId=', connectorId, 'isPrivate=', isPrivate)
|
|
91
91
|
|
|
92
92
|
const url = isPrivate && rcAccountId
|
|
93
|
-
? `${PORTAL_BASE}/connectors/${connectorId}/manifest?
|
|
93
|
+
? `${PORTAL_BASE}/connectors/${connectorId}/manifest?access=internal&type=connector&accountId=${encodeURIComponent(rcAccountId)}`
|
|
94
94
|
: `${PORTAL_BASE}/connectors/${connectorId}/manifest`
|
|
95
95
|
|
|
96
96
|
dbg.info('fetchManifest: GET', url)
|
package/package.json
CHANGED
|
@@ -1,72 +1,72 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@app-connect/core",
|
|
3
|
-
"version": "1.7.
|
|
4
|
-
"description": "RingCentral App Connect Core",
|
|
5
|
-
"main": "index.js",
|
|
6
|
-
"repository": {
|
|
7
|
-
"type": "git",
|
|
8
|
-
"url": "git+https://github.com/ringcentral/rc-unified-crm-extension.git"
|
|
9
|
-
},
|
|
10
|
-
"keywords": [
|
|
11
|
-
"RingCentral",
|
|
12
|
-
"App Connect"
|
|
13
|
-
],
|
|
14
|
-
"author": "RingCentral Labs",
|
|
15
|
-
"license": "MIT",
|
|
16
|
-
"peerDependencies": {
|
|
17
|
-
"axios": "^1.12.2",
|
|
18
|
-
"express": "^4.22.1",
|
|
19
|
-
"moment": "^2.29.4",
|
|
20
|
-
"moment-timezone": "^0.5.39",
|
|
21
|
-
"pg": "^8.8.0",
|
|
22
|
-
"sequelize": "^6.29.0"
|
|
23
|
-
},
|
|
24
|
-
"dependencies": {
|
|
25
|
-
"@aws-sdk/client-dynamodb": "^3.751.0",
|
|
26
|
-
"@aws-sdk/client-s3": "^3.947.0",
|
|
27
|
-
"@aws-sdk/s3-request-presigner": "^3.947.0",
|
|
28
|
-
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
29
|
-
"awesome-phonenumber": "^5.6.0",
|
|
30
|
-
"body-parser": "^1.20.4",
|
|
31
|
-
"body-parser-xml": "^2.0.5",
|
|
32
|
-
"client-oauth2": "^4.3.3",
|
|
33
|
-
"cors": "^2.8.5",
|
|
34
|
-
"country-state-city": "^3.2.1",
|
|
35
|
-
"dotenv": "^16.0.3",
|
|
36
|
-
"dynamoose": "^4.0.3",
|
|
37
|
-
"jsonwebtoken": "^9.0.0",
|
|
38
|
-
"mixpanel": "^0.18.0",
|
|
39
|
-
"shortid": "^2.2.17",
|
|
40
|
-
"tz-lookup": "^6.1.25",
|
|
41
|
-
"ua-parser-js": "^1.0.38"
|
|
42
|
-
},
|
|
43
|
-
"scripts": {
|
|
44
|
-
"test": "jest",
|
|
45
|
-
"test:watch": "jest --watch",
|
|
46
|
-
"test:coverage": "jest --coverage",
|
|
47
|
-
"test:ci": "jest --ci --coverage --watchAll=false"
|
|
48
|
-
},
|
|
49
|
-
"devDependencies": {
|
|
50
|
-
"@eslint/js": "^9.22.0",
|
|
51
|
-
"@octokit/rest": "^19.0.5",
|
|
52
|
-
"axios": "^1.12.2",
|
|
53
|
-
"eslint": "^9.22.0",
|
|
54
|
-
"express": "^4.22.1",
|
|
55
|
-
"globals": "^16.0.0",
|
|
56
|
-
"jest": "^29.3.1",
|
|
57
|
-
"moment": "^2.29.4",
|
|
58
|
-
"moment-timezone": "^0.5.39",
|
|
59
|
-
"nock": "^13.2.9",
|
|
60
|
-
"pg": "^8.8.0",
|
|
61
|
-
"sequelize": "^6.29.0",
|
|
62
|
-
"sqlite3": "^5.1.2",
|
|
63
|
-
"supertest": "^6.3.1"
|
|
64
|
-
},
|
|
65
|
-
"overrides": {
|
|
66
|
-
"js-object-utilities": "2.2.1"
|
|
67
|
-
},
|
|
68
|
-
"bugs": {
|
|
69
|
-
"url": "https://github.com/ringcentral/rc-unified-crm-extension/issues"
|
|
70
|
-
},
|
|
71
|
-
"homepage": "https://github.com/ringcentral/rc-unified-crm-extension#readme"
|
|
72
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@app-connect/core",
|
|
3
|
+
"version": "1.7.23",
|
|
4
|
+
"description": "RingCentral App Connect Core",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/ringcentral/rc-unified-crm-extension.git"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [
|
|
11
|
+
"RingCentral",
|
|
12
|
+
"App Connect"
|
|
13
|
+
],
|
|
14
|
+
"author": "RingCentral Labs",
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"peerDependencies": {
|
|
17
|
+
"axios": "^1.12.2",
|
|
18
|
+
"express": "^4.22.1",
|
|
19
|
+
"moment": "^2.29.4",
|
|
20
|
+
"moment-timezone": "^0.5.39",
|
|
21
|
+
"pg": "^8.8.0",
|
|
22
|
+
"sequelize": "^6.29.0"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@aws-sdk/client-dynamodb": "^3.751.0",
|
|
26
|
+
"@aws-sdk/client-s3": "^3.947.0",
|
|
27
|
+
"@aws-sdk/s3-request-presigner": "^3.947.0",
|
|
28
|
+
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
29
|
+
"awesome-phonenumber": "^5.6.0",
|
|
30
|
+
"body-parser": "^1.20.4",
|
|
31
|
+
"body-parser-xml": "^2.0.5",
|
|
32
|
+
"client-oauth2": "^4.3.3",
|
|
33
|
+
"cors": "^2.8.5",
|
|
34
|
+
"country-state-city": "^3.2.1",
|
|
35
|
+
"dotenv": "^16.0.3",
|
|
36
|
+
"dynamoose": "^4.0.3",
|
|
37
|
+
"jsonwebtoken": "^9.0.0",
|
|
38
|
+
"mixpanel": "^0.18.0",
|
|
39
|
+
"shortid": "^2.2.17",
|
|
40
|
+
"tz-lookup": "^6.1.25",
|
|
41
|
+
"ua-parser-js": "^1.0.38"
|
|
42
|
+
},
|
|
43
|
+
"scripts": {
|
|
44
|
+
"test": "jest",
|
|
45
|
+
"test:watch": "jest --watch",
|
|
46
|
+
"test:coverage": "jest --coverage",
|
|
47
|
+
"test:ci": "jest --ci --coverage --watchAll=false"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@eslint/js": "^9.22.0",
|
|
51
|
+
"@octokit/rest": "^19.0.5",
|
|
52
|
+
"axios": "^1.12.2",
|
|
53
|
+
"eslint": "^9.22.0",
|
|
54
|
+
"express": "^4.22.1",
|
|
55
|
+
"globals": "^16.0.0",
|
|
56
|
+
"jest": "^29.3.1",
|
|
57
|
+
"moment": "^2.29.4",
|
|
58
|
+
"moment-timezone": "^0.5.39",
|
|
59
|
+
"nock": "^13.2.9",
|
|
60
|
+
"pg": "^8.8.0",
|
|
61
|
+
"sequelize": "^6.29.0",
|
|
62
|
+
"sqlite3": "^5.1.2",
|
|
63
|
+
"supertest": "^6.3.1"
|
|
64
|
+
},
|
|
65
|
+
"overrides": {
|
|
66
|
+
"js-object-utilities": "2.2.1"
|
|
67
|
+
},
|
|
68
|
+
"bugs": {
|
|
69
|
+
"url": "https://github.com/ringcentral/rc-unified-crm-extension/issues"
|
|
70
|
+
},
|
|
71
|
+
"homepage": "https://github.com/ringcentral/rc-unified-crm-extension#readme"
|
|
72
|
+
}
|
package/releaseNotes.json
CHANGED
|
@@ -1,4 +1,20 @@
|
|
|
1
1
|
{
|
|
2
|
+
"1.7.23": {
|
|
3
|
+
"global": [
|
|
4
|
+
{
|
|
5
|
+
"type": "Rename",
|
|
6
|
+
"description": "Rename RingSense to ACE"
|
|
7
|
+
}
|
|
8
|
+
]
|
|
9
|
+
},
|
|
10
|
+
"1.7.22": {
|
|
11
|
+
"global": [
|
|
12
|
+
{
|
|
13
|
+
"type": "New",
|
|
14
|
+
"description": "Managed auth fields for non-OAuth platforms"
|
|
15
|
+
}
|
|
16
|
+
]
|
|
17
|
+
},
|
|
2
18
|
"1.7.21": {
|
|
3
19
|
"global": [
|
|
4
20
|
{
|
|
@@ -123,6 +123,39 @@ describe('Admin Handler', () => {
|
|
|
123
123
|
});
|
|
124
124
|
});
|
|
125
125
|
|
|
126
|
+
describe('validateRcUserToken', () => {
|
|
127
|
+
test('should return rc account and extension identity from valid token', async () => {
|
|
128
|
+
axios.get.mockResolvedValue({
|
|
129
|
+
data: {
|
|
130
|
+
account: { id: 'rc-account-789' },
|
|
131
|
+
id: 'extension-789',
|
|
132
|
+
contact: {
|
|
133
|
+
firstName: 'Alex',
|
|
134
|
+
lastName: 'Johnson'
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
const result = await adminHandler.validateRcUserToken({
|
|
140
|
+
rcAccessToken: 'valid-user-token'
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
expect(result).toEqual({
|
|
144
|
+
rcAccountId: 'rc-account-789',
|
|
145
|
+
rcExtensionId: 'extension-789'
|
|
146
|
+
});
|
|
147
|
+
expect(axios.get).toHaveBeenCalledWith(
|
|
148
|
+
'https://platform.ringcentral.com/restapi/v1.0/account/~/extension/~',
|
|
149
|
+
{ headers: { Authorization: 'Bearer valid-user-token' } }
|
|
150
|
+
);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
test('should throw when rcAccessToken is missing', async () => {
|
|
154
|
+
await expect(adminHandler.validateRcUserToken({})).rejects.toThrow('rcAccessToken is required');
|
|
155
|
+
expect(axios.get).not.toHaveBeenCalled();
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
|
|
126
159
|
describe('upsertAdminSettings', () => {
|
|
127
160
|
test('should create new admin config when none exists', async () => {
|
|
128
161
|
// Act
|