@memberjunction/server 5.49.0 → 5.50.0
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 +1 -1
- package/dist/auth/newUsers.d.ts.map +1 -1
- package/dist/auth/newUsers.js +6 -4
- package/dist/auth/newUsers.js.map +1 -1
- package/dist/generated/generated.d.ts +259 -14
- package/dist/generated/generated.d.ts.map +1 -1
- package/dist/generated/generated.js +1380 -73
- package/dist/generated/generated.js.map +1 -1
- package/dist/realtimeWidget/WidgetSessionService.d.ts +12 -1
- package/dist/realtimeWidget/WidgetSessionService.d.ts.map +1 -1
- package/dist/realtimeWidget/WidgetSessionService.js +23 -8
- package/dist/realtimeWidget/WidgetSessionService.js.map +1 -1
- package/dist/resolvers/IntegrationDiscoveryResolver.d.ts.map +1 -1
- package/dist/resolvers/IntegrationDiscoveryResolver.js +9 -4
- package/dist/resolvers/IntegrationDiscoveryResolver.js.map +1 -1
- package/package.json +91 -89
- package/src/__tests__/WidgetSessionService.test.ts +96 -0
- package/src/auth/newUsers.ts +6 -5
- package/src/generated/generated.ts +967 -55
- package/src/realtimeWidget/WidgetSessionService.ts +24 -8
- package/src/resolvers/IntegrationDiscoveryResolver.ts +9 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/server",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.50.0",
|
|
4
4
|
"description": "MemberJunction: This project provides API access via GraphQL to the common data store.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -27,93 +27,94 @@
|
|
|
27
27
|
"@as-integrations/express5": "^1.0.0",
|
|
28
28
|
"@graphql-tools/schema": "latest",
|
|
29
29
|
"@graphql-tools/utils": "^11.0.0",
|
|
30
|
-
"@memberjunction/actions": "5.
|
|
31
|
-
"@memberjunction/actions-apollo": "5.
|
|
32
|
-
"@memberjunction/actions-base": "5.
|
|
33
|
-
"@memberjunction/actions-bizapps-accounting": "5.
|
|
34
|
-
"@memberjunction/actions-bizapps-crm": "5.
|
|
35
|
-
"@memberjunction/actions-bizapps-formbuilders": "5.
|
|
36
|
-
"@memberjunction/actions-bizapps-lms": "5.
|
|
37
|
-
"@memberjunction/actions-bizapps-social": "5.
|
|
38
|
-
"@memberjunction/ai": "5.
|
|
39
|
-
"@memberjunction/ai-agent-manager": "5.
|
|
40
|
-
"@memberjunction/ai-agent-manager-actions": "5.
|
|
41
|
-
"@memberjunction/ai-agents": "5.
|
|
42
|
-
"@memberjunction/ai-bridge-base": "5.
|
|
43
|
-
"@memberjunction/ai-bridge-ringcentral": "5.
|
|
44
|
-
"@memberjunction/ai-bridge-server": "5.
|
|
45
|
-
"@memberjunction/ai-bridge-teams": "5.
|
|
46
|
-
"@memberjunction/ai-bridge-twilio": "5.
|
|
47
|
-
"@memberjunction/ai-bridge-vonage": "5.
|
|
48
|
-
"@memberjunction/ai-core-plus": "5.
|
|
49
|
-
"@memberjunction/ai-engine-base": "5.
|
|
50
|
-
"@memberjunction/ai-mcp-client": "5.
|
|
51
|
-
"@memberjunction/ai-prompts": "5.
|
|
52
|
-
"@memberjunction/ai-provider-bundle": "5.
|
|
53
|
-
"@memberjunction/ai-vector-sync": "5.
|
|
54
|
-
"@memberjunction/ai-vectordb": "5.
|
|
55
|
-
"@memberjunction/ai-vectors-pinecone": "5.
|
|
56
|
-
"@memberjunction/aiengine": "5.
|
|
57
|
-
"@memberjunction/api-keys": "5.
|
|
58
|
-
"@memberjunction/auth-providers": "5.
|
|
59
|
-
"@memberjunction/clustering-engine": "5.
|
|
60
|
-
"@memberjunction/codegen-lib": "5.
|
|
61
|
-
"@memberjunction/communication-engine": "5.
|
|
62
|
-
"@memberjunction/communication-ms-graph": "5.
|
|
63
|
-
"@memberjunction/
|
|
64
|
-
"@memberjunction/communication-
|
|
65
|
-
"@memberjunction/
|
|
66
|
-
"@memberjunction/
|
|
67
|
-
"@memberjunction/computer-use": "5.
|
|
68
|
-
"@memberjunction/
|
|
69
|
-
"@memberjunction/
|
|
70
|
-
"@memberjunction/core": "5.
|
|
71
|
-
"@memberjunction/core-
|
|
72
|
-
"@memberjunction/core-entities": "5.
|
|
73
|
-
"@memberjunction/
|
|
74
|
-
"@memberjunction/
|
|
75
|
-
"@memberjunction/data-context": "5.
|
|
76
|
-
"@memberjunction/
|
|
77
|
-
"@memberjunction/
|
|
78
|
-
"@memberjunction/
|
|
79
|
-
"@memberjunction/entity-communications-
|
|
80
|
-
"@memberjunction/
|
|
81
|
-
"@memberjunction/
|
|
82
|
-
"@memberjunction/
|
|
83
|
-
"@memberjunction/
|
|
84
|
-
"@memberjunction/
|
|
85
|
-
"@memberjunction/
|
|
86
|
-
"@memberjunction/integration-engine": "5.
|
|
87
|
-
"@memberjunction/integration-progress-artifacts": "5.
|
|
88
|
-
"@memberjunction/integration-schema-builder": "5.
|
|
89
|
-
"@memberjunction/interactive-component-types": "5.
|
|
90
|
-
"@memberjunction/lists": "5.
|
|
91
|
-
"@memberjunction/lists-base": "5.
|
|
92
|
-
"@memberjunction/livekit-room-server": "5.
|
|
93
|
-
"@memberjunction/
|
|
94
|
-
"@memberjunction/
|
|
95
|
-
"@memberjunction/
|
|
96
|
-
"@memberjunction/
|
|
97
|
-
"@memberjunction/
|
|
98
|
-
"@memberjunction/remote-browser-
|
|
99
|
-
"@memberjunction/remote-browser-
|
|
100
|
-
"@memberjunction/remote-browser-
|
|
101
|
-
"@memberjunction/
|
|
102
|
-
"@memberjunction/scheduling-
|
|
103
|
-
"@memberjunction/scheduling-
|
|
104
|
-
"@memberjunction/scheduling-engine
|
|
105
|
-
"@memberjunction/
|
|
106
|
-
"@memberjunction/
|
|
107
|
-
"@memberjunction/
|
|
108
|
-
"@memberjunction/
|
|
109
|
-
"@memberjunction/
|
|
110
|
-
"@memberjunction/
|
|
111
|
-
"@memberjunction/
|
|
112
|
-
"@memberjunction/tag-engine
|
|
113
|
-
"@memberjunction/
|
|
114
|
-
"@memberjunction/
|
|
115
|
-
"@memberjunction/testing-engine
|
|
116
|
-
"@memberjunction/
|
|
30
|
+
"@memberjunction/actions": "5.50.0",
|
|
31
|
+
"@memberjunction/actions-apollo": "5.50.0",
|
|
32
|
+
"@memberjunction/actions-base": "5.50.0",
|
|
33
|
+
"@memberjunction/actions-bizapps-accounting": "5.50.0",
|
|
34
|
+
"@memberjunction/actions-bizapps-crm": "5.50.0",
|
|
35
|
+
"@memberjunction/actions-bizapps-formbuilders": "5.50.0",
|
|
36
|
+
"@memberjunction/actions-bizapps-lms": "5.50.0",
|
|
37
|
+
"@memberjunction/actions-bizapps-social": "5.50.0",
|
|
38
|
+
"@memberjunction/ai": "5.50.0",
|
|
39
|
+
"@memberjunction/ai-agent-manager": "5.50.0",
|
|
40
|
+
"@memberjunction/ai-agent-manager-actions": "5.50.0",
|
|
41
|
+
"@memberjunction/ai-agents": "5.50.0",
|
|
42
|
+
"@memberjunction/ai-bridge-base": "5.50.0",
|
|
43
|
+
"@memberjunction/ai-bridge-ringcentral": "5.50.0",
|
|
44
|
+
"@memberjunction/ai-bridge-server": "5.50.0",
|
|
45
|
+
"@memberjunction/ai-bridge-teams": "5.50.0",
|
|
46
|
+
"@memberjunction/ai-bridge-twilio": "5.50.0",
|
|
47
|
+
"@memberjunction/ai-bridge-vonage": "5.50.0",
|
|
48
|
+
"@memberjunction/ai-core-plus": "5.50.0",
|
|
49
|
+
"@memberjunction/ai-engine-base": "5.50.0",
|
|
50
|
+
"@memberjunction/ai-mcp-client": "5.50.0",
|
|
51
|
+
"@memberjunction/ai-prompts": "5.50.0",
|
|
52
|
+
"@memberjunction/ai-provider-bundle": "5.50.0",
|
|
53
|
+
"@memberjunction/ai-vector-sync": "5.50.0",
|
|
54
|
+
"@memberjunction/ai-vectordb": "5.50.0",
|
|
55
|
+
"@memberjunction/ai-vectors-pinecone": "5.50.0",
|
|
56
|
+
"@memberjunction/aiengine": "5.50.0",
|
|
57
|
+
"@memberjunction/api-keys": "5.50.0",
|
|
58
|
+
"@memberjunction/auth-providers": "5.50.0",
|
|
59
|
+
"@memberjunction/clustering-engine": "5.50.0",
|
|
60
|
+
"@memberjunction/codegen-lib": "5.50.0",
|
|
61
|
+
"@memberjunction/communication-engine": "5.50.0",
|
|
62
|
+
"@memberjunction/communication-ms-graph": "5.50.0",
|
|
63
|
+
"@memberjunction/communication-sendgrid": "5.50.0",
|
|
64
|
+
"@memberjunction/communication-types": "5.50.0",
|
|
65
|
+
"@memberjunction/component-registry-client-sdk": "5.50.0",
|
|
66
|
+
"@memberjunction/computer-use": "5.50.0",
|
|
67
|
+
"@memberjunction/computer-use-engine": "5.50.0",
|
|
68
|
+
"@memberjunction/config": "5.50.0",
|
|
69
|
+
"@memberjunction/core": "5.50.0",
|
|
70
|
+
"@memberjunction/core-actions": "5.50.0",
|
|
71
|
+
"@memberjunction/core-entities": "5.50.0",
|
|
72
|
+
"@memberjunction/core-entities-server": "5.50.0",
|
|
73
|
+
"@memberjunction/credentials": "5.50.0",
|
|
74
|
+
"@memberjunction/data-context": "5.50.0",
|
|
75
|
+
"@memberjunction/data-context-server": "5.50.0",
|
|
76
|
+
"@memberjunction/doc-utils": "5.50.0",
|
|
77
|
+
"@memberjunction/encryption": "5.50.0",
|
|
78
|
+
"@memberjunction/entity-communications-base": "5.50.0",
|
|
79
|
+
"@memberjunction/entity-communications-server": "5.50.0",
|
|
80
|
+
"@memberjunction/esignature": "5.50.0",
|
|
81
|
+
"@memberjunction/external-change-detection": "5.50.0",
|
|
82
|
+
"@memberjunction/generic-database-provider": "5.50.0",
|
|
83
|
+
"@memberjunction/global": "5.50.0",
|
|
84
|
+
"@memberjunction/graphql-dataprovider": "5.50.0",
|
|
85
|
+
"@memberjunction/integration-engine": "5.50.0",
|
|
86
|
+
"@memberjunction/integration-engine-base": "5.50.0",
|
|
87
|
+
"@memberjunction/integration-progress-artifacts": "5.50.0",
|
|
88
|
+
"@memberjunction/integration-schema-builder": "5.50.0",
|
|
89
|
+
"@memberjunction/interactive-component-types": "5.50.0",
|
|
90
|
+
"@memberjunction/lists": "5.50.0",
|
|
91
|
+
"@memberjunction/lists-base": "5.50.0",
|
|
92
|
+
"@memberjunction/livekit-room-server": "5.50.0",
|
|
93
|
+
"@memberjunction/notifications": "5.50.0",
|
|
94
|
+
"@memberjunction/postgresql-dataprovider": "5.50.0",
|
|
95
|
+
"@memberjunction/queue": "5.50.0",
|
|
96
|
+
"@memberjunction/record-comparison": "5.50.0",
|
|
97
|
+
"@memberjunction/redis-provider": "5.50.0",
|
|
98
|
+
"@memberjunction/remote-browser-base": "5.50.0",
|
|
99
|
+
"@memberjunction/remote-browser-cdp": "5.50.0",
|
|
100
|
+
"@memberjunction/remote-browser-selfhost": "5.50.0",
|
|
101
|
+
"@memberjunction/remote-browser-server": "5.50.0",
|
|
102
|
+
"@memberjunction/scheduling-actions": "5.50.0",
|
|
103
|
+
"@memberjunction/scheduling-base-types": "5.50.0",
|
|
104
|
+
"@memberjunction/scheduling-engine": "5.50.0",
|
|
105
|
+
"@memberjunction/scheduling-engine-base": "5.50.0",
|
|
106
|
+
"@memberjunction/schema-engine": "5.50.0",
|
|
107
|
+
"@memberjunction/search-engine": "5.50.0",
|
|
108
|
+
"@memberjunction/server-extensions-core": "5.50.0",
|
|
109
|
+
"@memberjunction/sql-dialect": "5.50.0",
|
|
110
|
+
"@memberjunction/sqlserver-dataprovider": "5.50.0",
|
|
111
|
+
"@memberjunction/storage": "5.50.0",
|
|
112
|
+
"@memberjunction/tag-engine": "5.50.0",
|
|
113
|
+
"@memberjunction/tag-engine-base": "5.50.0",
|
|
114
|
+
"@memberjunction/templates": "5.50.0",
|
|
115
|
+
"@memberjunction/testing-engine": "5.50.0",
|
|
116
|
+
"@memberjunction/testing-engine-base": "5.50.0",
|
|
117
|
+
"@memberjunction/version-history": "5.50.0",
|
|
117
118
|
"@octokit/auth-app": "^7.1.5",
|
|
118
119
|
"@octokit/rest": "^21.1.1",
|
|
119
120
|
"@types/compression": "^1.8.1",
|
|
@@ -150,9 +151,10 @@
|
|
|
150
151
|
"typedi": "^0.10.0",
|
|
151
152
|
"uuid": "^13.0.0",
|
|
152
153
|
"ws": "^8.19.0",
|
|
153
|
-
"zod": "
|
|
154
|
+
"zod": "^3.25.0"
|
|
154
155
|
},
|
|
155
156
|
"devDependencies": {
|
|
157
|
+
"@types/express": "^4.17.25",
|
|
156
158
|
"pkgroll": "2.23.0",
|
|
157
159
|
"typescript": "^5.9.3",
|
|
158
160
|
"vitest": "^3.1.1"
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
+
|
|
3
|
+
// WidgetSessionService is the imperative shell for public widget sessions — importing it pulls in
|
|
4
|
+
// config.ts (which eagerly validates DB env vars at module load) plus the full magic-link /
|
|
5
|
+
// returning-visitor / communication stacks. This suite only exercises the `ResolvePerInstanceRateLimit`
|
|
6
|
+
// cache-bounding behavior, so stub those transitive deps out (mirrors the pattern already established
|
|
7
|
+
// in `magicLinkService.provisionLog.test.ts` for testing another imperative-shell class).
|
|
8
|
+
vi.mock('../config.js', () => ({
|
|
9
|
+
configInfo: {},
|
|
10
|
+
}));
|
|
11
|
+
vi.mock('@memberjunction/sqlserver-dataprovider', () => ({
|
|
12
|
+
UserCache: {
|
|
13
|
+
Instance: { Users: [], UserByName: () => undefined, GetSystemUser: () => undefined },
|
|
14
|
+
Users: [],
|
|
15
|
+
},
|
|
16
|
+
}));
|
|
17
|
+
vi.mock('../auth/magicLink/MagicLinkService.js', () => ({
|
|
18
|
+
MagicLinkService: class {},
|
|
19
|
+
}));
|
|
20
|
+
vi.mock('../agentSessions/ReturningVisitorRecap.js', () => ({
|
|
21
|
+
writeReturningVisitorRecap: async () => undefined,
|
|
22
|
+
}));
|
|
23
|
+
vi.mock('../realtimeWidget/visitorIdentity.js', () => ({
|
|
24
|
+
resolveIdentityByEmail: async () => null,
|
|
25
|
+
mergeVisitorIdentity: async () => 0,
|
|
26
|
+
forgetVisitor: async () => ({ notesArchived: 0, conversationsCleared: 0 }),
|
|
27
|
+
}));
|
|
28
|
+
|
|
29
|
+
import { WidgetSessionService } from '../realtimeWidget/WidgetSessionService.js';
|
|
30
|
+
import type { WidgetConfig } from '../config.js';
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Minimal `WidgetConfig` matching the zod schema's post-parse (defaulted) shape —
|
|
34
|
+
* enough for `ResolvePerInstanceRateLimit`, which never dereferences most of these.
|
|
35
|
+
*/
|
|
36
|
+
function makeConfig(overrides: Partial<WidgetConfig> = {}): WidgetConfig {
|
|
37
|
+
return {
|
|
38
|
+
enabled: true,
|
|
39
|
+
signingReuse: 'magic-link',
|
|
40
|
+
audience: 'mj-magic-link',
|
|
41
|
+
anonymousEmail: 'anonymous@magic-link.local',
|
|
42
|
+
defaultSessionTtlMinutes: 15,
|
|
43
|
+
defaultRateLimitPerMinute: 30,
|
|
44
|
+
rateLimitWindowMs: 60_000,
|
|
45
|
+
voiceDefaultMaxSessionMinutes: 10,
|
|
46
|
+
hostPublicKeys: {},
|
|
47
|
+
...overrides,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
describe('WidgetSessionService — ResolvePerInstanceRateLimit', () => {
|
|
52
|
+
it('returns the deployment-wide default for an empty widget key without touching the cache', async () => {
|
|
53
|
+
const service = new WidgetSessionService('https://mj.example.com', makeConfig({ defaultRateLimitPerMinute: 42 }));
|
|
54
|
+
await expect(service.ResolvePerInstanceRateLimit('')).resolves.toBe(42);
|
|
55
|
+
expect(service.RateLimitCacheSize).toBe(0);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('falls back to the default (and still caches) when the widget key cannot be resolved (no DB in unit tests)', async () => {
|
|
59
|
+
const service = new WidgetSessionService('https://mj.example.com', makeConfig({ defaultRateLimitPerMinute: 30 }));
|
|
60
|
+
await expect(service.ResolvePerInstanceRateLimit('pk_live_unknown')).resolves.toBe(30);
|
|
61
|
+
expect(service.RateLimitCacheSize).toBe(1);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('caches a resolved limit per key instead of re-resolving on every call', async () => {
|
|
65
|
+
const service = new WidgetSessionService('https://mj.example.com', makeConfig());
|
|
66
|
+
await service.ResolvePerInstanceRateLimit('pk_live_same_key');
|
|
67
|
+
await service.ResolvePerInstanceRateLimit('pk_live_same_key');
|
|
68
|
+
await service.ResolvePerInstanceRateLimit('pk_live_same_key');
|
|
69
|
+
expect(service.RateLimitCacheSize).toBe(1);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it(
|
|
73
|
+
'never grows the rate-limit cache past its configured bound, even under an unbounded stream of ' +
|
|
74
|
+
'distinct attacker-supplied widget keys (Memory Leak Audit Round 8, Critical finding — the cache ' +
|
|
75
|
+
'key is unauthenticated request input on the public /widget/session endpoint)',
|
|
76
|
+
async () => {
|
|
77
|
+
const service = new WidgetSessionService('https://mj.example.com', makeConfig());
|
|
78
|
+
// Far more distinct keys than any real deployment's widget-instance count, and comfortably
|
|
79
|
+
// more than the cache's configured max size — simulates an attacker sending a fresh garbage
|
|
80
|
+
// widgetKey on every request.
|
|
81
|
+
const distinctKeyCount = 12_000;
|
|
82
|
+
for (let i = 0; i < distinctKeyCount; i++) {
|
|
83
|
+
await service.ResolvePerInstanceRateLimit(`pk_live_attacker_${i}`);
|
|
84
|
+
}
|
|
85
|
+
expect(service.RateLimitCacheSize).toBeLessThan(distinctKeyCount);
|
|
86
|
+
expect(service.RateLimitCacheSize).toBeLessThanOrEqual(10_000);
|
|
87
|
+
},
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
it('trims whitespace before using the key to look up / populate the cache', async () => {
|
|
91
|
+
const service = new WidgetSessionService('https://mj.example.com', makeConfig());
|
|
92
|
+
await service.ResolvePerInstanceRateLimit(' pk_live_padded ');
|
|
93
|
+
await service.ResolvePerInstanceRateLimit('pk_live_padded');
|
|
94
|
+
expect(service.RateLimitCacheSize).toBe(1);
|
|
95
|
+
});
|
|
96
|
+
});
|
package/src/auth/newUsers.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { ApplicationInfo, DatabaseProviderBase, EntitySaveOptions, LogError, Log
|
|
|
2
2
|
import { RegisterClass } from "@memberjunction/global";
|
|
3
3
|
import { UserCache } from "@memberjunction/sqlserver-dataprovider";
|
|
4
4
|
import { configInfo } from "../config.js";
|
|
5
|
-
import { MJUserEntity, MJUserRoleEntity, MJUserApplicationEntity, MJUserApplicationEntityEntity, MJApplicationEntityType, MJApplicationEntityEntityType } from "@memberjunction/core-entities";
|
|
5
|
+
import { MJUserEntity, MJUserRoleEntity, MJUserApplicationEntity, MJUserApplicationEntityEntity, MJApplicationEntityType, MJApplicationEntityEntityType, UserInfoEngine } from "@memberjunction/core-entities";
|
|
6
6
|
|
|
7
7
|
export class NewUserBase {
|
|
8
8
|
public async createNewUser(firstName: string, lastName: string, email: string, linkedRecordType: string = 'None', linkedEntityId?: string, linkedEntityRecordId?: string): Promise<MJUserEntity | null> {
|
|
@@ -90,10 +90,11 @@ export class NewUserBase {
|
|
|
90
90
|
}
|
|
91
91
|
} else {
|
|
92
92
|
LogStatus(`No UserApplications configured, using DefaultForNewUser applications for new user ${user.Name}`);
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
93
|
+
// Bug F2: use the shared selector, which filters to Active apps flagged
|
|
94
|
+
// DefaultForNewUser (in DefaultSequence order). This path previously omitted the
|
|
95
|
+
// Status = 'Active' check, so an inactive default app could be provisioned here.
|
|
96
|
+
applicationsToCreate = UserInfoEngine.GetDefaultApplicationsForNewUser(md);
|
|
97
|
+
LogStatus(`Found ${applicationsToCreate.length} active applications with DefaultForNewUser=true`);
|
|
97
98
|
}
|
|
98
99
|
|
|
99
100
|
for (const [appIndex, application] of applicationsToCreate.entries()) {
|