@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.
@@ -0,0 +1,127 @@
1
+ const getSessionInfo = require('../../../mcp/tools/getSessionInfo');
2
+ const jwt = require('../../../lib/jwt');
3
+ const { UserModel } = require('../../../models/userModel');
4
+ const { RingCentral } = require('../../../lib/ringcentral');
5
+
6
+ jest.mock('../../../lib/jwt');
7
+ jest.mock('../../../models/userModel');
8
+ jest.mock('../../../lib/ringcentral');
9
+
10
+ describe('MCP Tool: getSessionInfo', () => {
11
+ beforeEach(() => {
12
+ jest.clearAllMocks();
13
+ RingCentral.mockImplementation(() => ({
14
+ getExtensionInfo: jest.fn().mockResolvedValue({ name: 'Demo Extension' })
15
+ }));
16
+ });
17
+
18
+ describe('tool definition', () => {
19
+ test('should have correct tool definition', () => {
20
+ expect(getSessionInfo.definition).toBeDefined();
21
+ expect(getSessionInfo.definition.name).toBe('getSessionInfo');
22
+ expect(getSessionInfo.definition.description).toContain('session info');
23
+ expect(getSessionInfo.definition.inputSchema).toBeDefined();
24
+ expect(getSessionInfo.definition.inputSchema.properties).toEqual({});
25
+ });
26
+ });
27
+
28
+ describe('execute', () => {
29
+ test('should return unauthenticated session info when no CRM jwtToken exists', async () => {
30
+ const result = await getSessionInfo.execute({
31
+ openaiSessionId: 'session-123',
32
+ rcExtensionId: 'ext-456',
33
+ rcAccessToken: 'rc-token'
34
+ });
35
+
36
+ expect(result).toEqual({
37
+ success: true,
38
+ data: {
39
+ openaiSessionId: 'session-123',
40
+ dataToShow: {
41
+ isCrmAuthenticated: false,
42
+ ringcentral: {
43
+ extensionId: 'ext-456',
44
+ name: 'Demo Extension',
45
+ },
46
+ crm: {
47
+ userId: null,
48
+ platform: null,
49
+ hostname: null
50
+ }
51
+ }
52
+ }
53
+ });
54
+ expect(jwt.decodeJwt).not.toHaveBeenCalled();
55
+ expect(UserModel.findByPk).not.toHaveBeenCalled();
56
+ });
57
+
58
+ test('should return connected CRM session info when jwtToken resolves to a saved user', async () => {
59
+ jwt.decodeJwt.mockReturnValue({
60
+ id: 'crm-user-1',
61
+ platform: 'clio'
62
+ });
63
+ UserModel.findByPk.mockResolvedValue({
64
+ id: 'crm-user-1',
65
+ platform: 'clio',
66
+ hostname: 'app.clio.com',
67
+ accessToken: 'crm-access-token',
68
+ });
69
+
70
+ const result = await getSessionInfo.execute({
71
+ openaiSessionId: 'session-123',
72
+ rcExtensionId: 'ext-456',
73
+ rcAccessToken: 'rc-token',
74
+ jwtToken: 'jwt-token'
75
+ });
76
+
77
+ expect(jwt.decodeJwt).toHaveBeenCalledWith('jwt-token');
78
+ expect(UserModel.findByPk).toHaveBeenCalledWith('crm-user-1');
79
+ expect(result).toEqual({
80
+ success: true,
81
+ data: {
82
+ openaiSessionId: 'session-123',
83
+ dataToShow: {
84
+ isCrmAuthenticated: true,
85
+ ringcentral: {
86
+ extensionId: 'ext-456',
87
+ name: 'Demo Extension',
88
+ },
89
+ crm: {
90
+ userId: 'crm-user-1',
91
+ platform: 'clio',
92
+ hostname: 'app.clio.com'
93
+ }
94
+ }
95
+ }
96
+ });
97
+ });
98
+
99
+ test('should report not authenticated when jwtToken is invalid', async () => {
100
+ jwt.decodeJwt.mockReturnValue(null);
101
+
102
+ const result = await getSessionInfo.execute({
103
+ jwtToken: 'bad-token'
104
+ });
105
+
106
+ expect(result).toEqual({
107
+ success: true,
108
+ data: {
109
+ openaiSessionId: null,
110
+ dataToShow: {
111
+ isCrmAuthenticated: false,
112
+ ringcentral: {
113
+ extensionId: null,
114
+ name: null,
115
+ },
116
+ crm: {
117
+ userId: null,
118
+ platform: null,
119
+ hostname: null
120
+ }
121
+ }
122
+ }
123
+ });
124
+ expect(UserModel.findByPk).not.toHaveBeenCalled();
125
+ });
126
+ });
127
+ });
@@ -1,16 +1,22 @@
1
1
  const logout = require('../../../mcp/tools/logout');
2
2
  const jwt = require('../../../lib/jwt');
3
3
  const { UserModel } = require('../../../models/userModel');
4
+ const { LlmSessionModel } = require('../../../models/llmSessionModel');
5
+ const { CacheModel } = require('../../../models/cacheModel');
4
6
  const connectorRegistry = require('../../../connector/registry');
5
7
 
6
8
  // Mock dependencies
7
9
  jest.mock('../../../lib/jwt');
8
10
  jest.mock('../../../models/userModel');
11
+ jest.mock('../../../models/llmSessionModel');
12
+ jest.mock('../../../models/cacheModel');
9
13
  jest.mock('../../../connector/registry');
10
14
 
11
15
  describe('MCP Tool: logout', () => {
12
16
  beforeEach(() => {
13
17
  jest.clearAllMocks();
18
+ LlmSessionModel.destroy.mockResolvedValue(1);
19
+ CacheModel.destroy.mockResolvedValue(1);
14
20
  });
15
21
 
16
22
  describe('tool definition', () => {
@@ -65,6 +71,7 @@ describe('MCP Tool: logout', () => {
65
71
  }
66
72
  });
67
73
  expect(jwt.decodeJwt).toHaveBeenCalledWith('mock-jwt-token');
74
+ expect(LlmSessionModel.destroy).toHaveBeenCalledWith({ where: { id: 'test-user-id' } });
68
75
  expect(UserModel.findByPk).toHaveBeenCalledWith('test-user-id');
69
76
  expect(connectorRegistry.getConnector).toHaveBeenCalledWith('testCRM');
70
77
  expect(mockConnector.unAuthorize).toHaveBeenCalledWith({
@@ -170,6 +177,57 @@ describe('MCP Tool: logout', () => {
170
177
  expect(consoleSpy).toHaveBeenCalled();
171
178
  consoleSpy.mockRestore();
172
179
  });
180
+
181
+ test('should clear both CRM user and RC extension session rows when rcExtensionId is provided', async () => {
182
+ const mockUser = {
183
+ id: 'test-user-id',
184
+ platform: 'testCRM'
185
+ };
186
+
187
+ jwt.decodeJwt.mockReturnValue({
188
+ id: 'test-user-id',
189
+ platform: 'testCRM'
190
+ });
191
+ UserModel.findByPk.mockResolvedValue(mockUser);
192
+ connectorRegistry.getConnector.mockReturnValue({
193
+ unAuthorize: jest.fn().mockResolvedValue({})
194
+ });
195
+
196
+ const result = await logout.execute({
197
+ jwtToken: 'mock-jwt-token',
198
+ rcExtensionId: 'rc-ext-123'
199
+ });
200
+
201
+ expect(result.success).toBe(true);
202
+ expect(LlmSessionModel.destroy).toHaveBeenNthCalledWith(1, { where: { id: 'test-user-id' } });
203
+ expect(LlmSessionModel.destroy).toHaveBeenNthCalledWith(2, { where: { id: 'rc-ext-123' } });
204
+ });
205
+
206
+ test('should clear the resolved rcExtension cache for the current OpenAI session on logout', async () => {
207
+ const mockUser = {
208
+ id: 'test-user-id',
209
+ platform: 'testCRM'
210
+ };
211
+
212
+ jwt.decodeJwt.mockReturnValue({
213
+ id: 'test-user-id',
214
+ platform: 'testCRM'
215
+ });
216
+ UserModel.findByPk.mockResolvedValue(mockUser);
217
+ connectorRegistry.getConnector.mockReturnValue({
218
+ unAuthorize: jest.fn().mockResolvedValue({})
219
+ });
220
+
221
+ const result = await logout.execute({
222
+ jwtToken: 'mock-jwt-token',
223
+ openaiSessionId: 'oa-session-123'
224
+ });
225
+
226
+ expect(result.success).toBe(true);
227
+ expect(CacheModel.destroy).toHaveBeenCalledWith({
228
+ where: { id: 'oa-session-123-rcExtensionId' }
229
+ });
230
+ });
173
231
  });
174
232
  });
175
233
 
@@ -47,7 +47,6 @@ describe('Managed Auth Routes', () => {
47
47
  adminCore.validateRcUserToken.mockResolvedValue({
48
48
  rcAccountId: 'validated-account-id',
49
49
  rcExtensionId: 'validated-extension-id',
50
- rcUserName: 'Validated User',
51
50
  });
52
51
  managedAuthCore.getManagedAuthState.mockResolvedValue({
53
52
  hasManagedAuth: true,
@@ -95,7 +94,6 @@ describe('Managed Auth Routes', () => {
95
94
  adminCore.validateRcUserToken.mockResolvedValue({
96
95
  rcAccountId: 'validated-account-id',
97
96
  rcExtensionId: 'validated-extension-id',
98
- rcUserName: 'Validated User',
99
97
  });
100
98
  authCore.onApiKeyLogin.mockResolvedValue({
101
99
  userInfo: {
@@ -125,7 +123,6 @@ describe('Managed Auth Routes', () => {
125
123
  platform: 'testCRM',
126
124
  rcAccountId: 'validated-account-id',
127
125
  rcExtensionId: 'validated-extension-id',
128
- rcUserName: 'Validated User',
129
126
  }));
130
127
  });
131
128
  });