@memberjunction/server 5.8.0 → 5.9.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 -0
- package/dist/apolloServer/index.d.ts +10 -2
- package/dist/apolloServer/index.d.ts.map +1 -1
- package/dist/apolloServer/index.js +22 -8
- package/dist/apolloServer/index.js.map +1 -1
- package/dist/config.d.ts +125 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +23 -0
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts +17 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +144 -62
- package/dist/context.js.map +1 -1
- package/dist/generated/generated.d.ts +207 -0
- package/dist/generated/generated.d.ts.map +1 -1
- package/dist/generated/generated.js +1112 -76
- package/dist/generated/generated.js.map +1 -1
- package/dist/generic/CacheInvalidationResolver.d.ts +32 -0
- package/dist/generic/CacheInvalidationResolver.d.ts.map +1 -0
- package/dist/generic/CacheInvalidationResolver.js +80 -0
- package/dist/generic/CacheInvalidationResolver.js.map +1 -0
- package/dist/generic/PubSubManager.d.ts +27 -0
- package/dist/generic/PubSubManager.d.ts.map +1 -0
- package/dist/generic/PubSubManager.js +42 -0
- package/dist/generic/PubSubManager.js.map +1 -0
- package/dist/generic/ResolverBase.d.ts +14 -0
- package/dist/generic/ResolverBase.d.ts.map +1 -1
- package/dist/generic/ResolverBase.js +50 -0
- package/dist/generic/ResolverBase.js.map +1 -1
- package/dist/hooks.d.ts +65 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +14 -0
- package/dist/hooks.js.map +1 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +172 -45
- package/dist/index.js.map +1 -1
- package/dist/multiTenancy/index.d.ts +47 -0
- package/dist/multiTenancy/index.d.ts.map +1 -0
- package/dist/multiTenancy/index.js +152 -0
- package/dist/multiTenancy/index.js.map +1 -0
- package/dist/resolvers/IntegrationDiscoveryResolver.d.ts +123 -0
- package/dist/resolvers/IntegrationDiscoveryResolver.d.ts.map +1 -0
- package/dist/resolvers/IntegrationDiscoveryResolver.js +624 -0
- package/dist/resolvers/IntegrationDiscoveryResolver.js.map +1 -0
- package/dist/rest/RESTEndpointHandler.d.ts +3 -1
- package/dist/rest/RESTEndpointHandler.d.ts.map +1 -1
- package/dist/rest/RESTEndpointHandler.js +14 -33
- package/dist/rest/RESTEndpointHandler.js.map +1 -1
- package/dist/types.d.ts +9 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +61 -57
- package/src/__tests__/multiTenancy.security.test.ts +334 -0
- package/src/__tests__/multiTenancy.test.ts +225 -0
- package/src/__tests__/unifiedAuth.test.ts +416 -0
- package/src/apolloServer/index.ts +32 -16
- package/src/config.ts +25 -0
- package/src/context.ts +205 -98
- package/src/generated/generated.ts +736 -1
- package/src/generic/CacheInvalidationResolver.ts +66 -0
- package/src/generic/PubSubManager.ts +47 -0
- package/src/generic/ResolverBase.ts +53 -0
- package/src/hooks.ts +77 -0
- package/src/index.ts +198 -49
- package/src/multiTenancy/index.ts +183 -0
- package/src/resolvers/IntegrationDiscoveryResolver.ts +584 -0
- package/src/rest/RESTEndpointHandler.ts +23 -42
- package/src/types.ts +10 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-tenant data separation framework.
|
|
3
|
+
*
|
|
4
|
+
* Provides factory functions that create Express middleware and provider hooks
|
|
5
|
+
* based on the `multiTenancy` section of mj.config.cjs. All functions return
|
|
6
|
+
* standard hook/middleware types from WS2 so they integrate seamlessly with
|
|
7
|
+
* the MJServer extensibility system.
|
|
8
|
+
*/
|
|
9
|
+
import { Metadata } from '@memberjunction/core';
|
|
10
|
+
/**
|
|
11
|
+
* Creates Express middleware that resolves and attaches TenantContext
|
|
12
|
+
* to the authenticated user's UserInfo for each request.
|
|
13
|
+
*
|
|
14
|
+
* This middleware runs in the post-auth slot (after `createUnifiedAuthMiddleware`)
|
|
15
|
+
* so `req.userPayload` is available. It reads the tenant ID from the configured
|
|
16
|
+
* source and attaches it directly to `userPayload.userRecord.TenantContext`.
|
|
17
|
+
*
|
|
18
|
+
* By the time GraphQL resolvers or REST handlers run, the contextUser already
|
|
19
|
+
* has TenantContext set — no deferred pickup via `req['__mj_tenantId']` needed.
|
|
20
|
+
*/
|
|
21
|
+
export function createTenantMiddleware(config) {
|
|
22
|
+
return (req, _res, next) => {
|
|
23
|
+
const userPayload = req.userPayload;
|
|
24
|
+
if (!userPayload?.userRecord) {
|
|
25
|
+
// No authenticated user — skip tenant resolution
|
|
26
|
+
next();
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if (config.contextSource === 'header') {
|
|
30
|
+
const tenantId = req.headers[config.tenantHeader.toLowerCase()];
|
|
31
|
+
if (tenantId) {
|
|
32
|
+
attachTenantContext(userPayload.userRecord, tenantId, 'header');
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
next();
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Attaches TenantContext to a UserInfo object.
|
|
40
|
+
* Called from the GraphQL context function after authentication.
|
|
41
|
+
*/
|
|
42
|
+
export function attachTenantContext(user, tenantId, source) {
|
|
43
|
+
user.TenantContext = { TenantID: tenantId, Source: source };
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Determines whether a given entity name should have tenant filtering applied.
|
|
47
|
+
*/
|
|
48
|
+
function isEntityScoped(entityName, config) {
|
|
49
|
+
// Auto-exclude core MJ entities (entities in the __mj schema)
|
|
50
|
+
if (config.autoExcludeCoreEntities) {
|
|
51
|
+
const md = new Metadata();
|
|
52
|
+
const entity = md.Entities.find(e => e.Name.trim().toLowerCase() === entityName.trim().toLowerCase());
|
|
53
|
+
if (entity && entity.SchemaName === '__mj') {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const normalizedName = entityName.trim().toLowerCase();
|
|
58
|
+
const normalizedScoped = config.scopedEntities.map(e => e.trim().toLowerCase());
|
|
59
|
+
if (config.scopingStrategy === 'allowlist') {
|
|
60
|
+
// Only entities explicitly listed are scoped
|
|
61
|
+
return normalizedScoped.includes(normalizedName);
|
|
62
|
+
}
|
|
63
|
+
// Denylist: all entities are scoped EXCEPT those listed
|
|
64
|
+
return !normalizedScoped.includes(normalizedName);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Checks if a user has an admin role that bypasses tenant filtering.
|
|
68
|
+
*/
|
|
69
|
+
function isAdminUser(user, adminRoles) {
|
|
70
|
+
if (!user.UserRoles || user.UserRoles.length === 0)
|
|
71
|
+
return false;
|
|
72
|
+
const normalizedAdmin = adminRoles.map(r => r.trim().toLowerCase());
|
|
73
|
+
return user.UserRoles.some(ur => normalizedAdmin.includes(ur.Role?.trim().toLowerCase() ?? ''));
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Creates a PreRunViewHook that auto-injects tenant WHERE clauses
|
|
77
|
+
* into RunView queries for scoped entities.
|
|
78
|
+
*/
|
|
79
|
+
export function createTenantPreRunViewHook(config) {
|
|
80
|
+
return (params, contextUser) => {
|
|
81
|
+
// No tenant context → no filtering
|
|
82
|
+
if (!contextUser?.TenantContext)
|
|
83
|
+
return params;
|
|
84
|
+
// Admin users bypass tenant filtering
|
|
85
|
+
if (isAdminUser(contextUser, config.adminRoles))
|
|
86
|
+
return params;
|
|
87
|
+
// Resolve entity name from params
|
|
88
|
+
const entityName = params.EntityName;
|
|
89
|
+
if (!entityName)
|
|
90
|
+
return params; // Can't filter without knowing the entity
|
|
91
|
+
// Check if this entity should be scoped
|
|
92
|
+
if (!isEntityScoped(entityName, config))
|
|
93
|
+
return params;
|
|
94
|
+
// Determine which column holds the tenant ID
|
|
95
|
+
const tenantColumn = config.entityColumnMappings[entityName] ?? config.defaultTenantColumn;
|
|
96
|
+
const tenantFilter = `[${tenantColumn}] = '${contextUser.TenantContext.TenantID}'`;
|
|
97
|
+
// Inject the tenant filter
|
|
98
|
+
if (params.ExtraFilter && typeof params.ExtraFilter === 'string' && params.ExtraFilter.trim().length > 0) {
|
|
99
|
+
params.ExtraFilter = `(${params.ExtraFilter}) AND ${tenantFilter}`;
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
params.ExtraFilter = tenantFilter;
|
|
103
|
+
}
|
|
104
|
+
return params;
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Creates a PreSaveHook that validates the tenant column on writes.
|
|
109
|
+
*
|
|
110
|
+
* In 'strict' mode, rejects saves where the tenant column value doesn't
|
|
111
|
+
* match the user's TenantContext. In 'log' mode, warns but allows. In
|
|
112
|
+
* 'off' mode, this hook is a no-op.
|
|
113
|
+
*/
|
|
114
|
+
export function createTenantPreSaveHook(config) {
|
|
115
|
+
return (entity, contextUser) => {
|
|
116
|
+
// No validation needed if write protection is off
|
|
117
|
+
if (config.writeProtection === 'off')
|
|
118
|
+
return true;
|
|
119
|
+
// No tenant context → no validation
|
|
120
|
+
if (!contextUser?.TenantContext)
|
|
121
|
+
return true;
|
|
122
|
+
// Admin users bypass write validation
|
|
123
|
+
if (isAdminUser(contextUser, config.adminRoles))
|
|
124
|
+
return true;
|
|
125
|
+
// Check if this entity should be scoped
|
|
126
|
+
const entityName = entity.EntityInfo?.Name;
|
|
127
|
+
if (!entityName)
|
|
128
|
+
return true;
|
|
129
|
+
if (!isEntityScoped(entityName, config))
|
|
130
|
+
return true;
|
|
131
|
+
// Determine which column holds the tenant ID
|
|
132
|
+
const tenantColumn = config.entityColumnMappings[entityName] ?? config.defaultTenantColumn;
|
|
133
|
+
// Get the value of the tenant column from the entity
|
|
134
|
+
const tenantFieldValue = entity.Get(tenantColumn);
|
|
135
|
+
// For new records without the tenant column set, auto-assign the tenant ID
|
|
136
|
+
if (!entity.IsSaved && (tenantFieldValue === null || tenantFieldValue === undefined)) {
|
|
137
|
+
entity.Set(tenantColumn, contextUser.TenantContext.TenantID);
|
|
138
|
+
return true;
|
|
139
|
+
}
|
|
140
|
+
// Validate the tenant column matches
|
|
141
|
+
if (tenantFieldValue && String(tenantFieldValue) !== contextUser.TenantContext.TenantID) {
|
|
142
|
+
const message = `Save rejected: ${entityName} record belongs to tenant '${tenantFieldValue}' but user is in tenant '${contextUser.TenantContext.TenantID}'`;
|
|
143
|
+
if (config.writeProtection === 'strict') {
|
|
144
|
+
return message; // Reject with error message
|
|
145
|
+
}
|
|
146
|
+
// 'log' mode — warn but allow
|
|
147
|
+
console.warn(`[MultiTenancy] ${message}`);
|
|
148
|
+
}
|
|
149
|
+
return true;
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/multiTenancy/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { ResolverBase } from "../generic/ResolverBase.js";
|
|
2
|
+
import { AppContext } from "../types.js";
|
|
3
|
+
declare class ExternalObjectOutput {
|
|
4
|
+
Name: string;
|
|
5
|
+
Label: string;
|
|
6
|
+
SupportsIncrementalSync: boolean;
|
|
7
|
+
SupportsWrite: boolean;
|
|
8
|
+
}
|
|
9
|
+
declare class DiscoverObjectsOutput {
|
|
10
|
+
Success: boolean;
|
|
11
|
+
Message: string;
|
|
12
|
+
Objects?: ExternalObjectOutput[];
|
|
13
|
+
}
|
|
14
|
+
declare class ExternalFieldOutput {
|
|
15
|
+
Name: string;
|
|
16
|
+
Label: string;
|
|
17
|
+
DataType: string;
|
|
18
|
+
IsRequired: boolean;
|
|
19
|
+
IsUniqueKey: boolean;
|
|
20
|
+
IsReadOnly: boolean;
|
|
21
|
+
}
|
|
22
|
+
declare class DiscoverFieldsOutput {
|
|
23
|
+
Success: boolean;
|
|
24
|
+
Message: string;
|
|
25
|
+
Fields?: ExternalFieldOutput[];
|
|
26
|
+
}
|
|
27
|
+
declare class ConnectionTestOutput {
|
|
28
|
+
Success: boolean;
|
|
29
|
+
Message: string;
|
|
30
|
+
ServerVersion?: string;
|
|
31
|
+
}
|
|
32
|
+
declare class PreviewRecordOutput {
|
|
33
|
+
Data: string;
|
|
34
|
+
}
|
|
35
|
+
declare class PreviewDataOutput {
|
|
36
|
+
Success: boolean;
|
|
37
|
+
Message: string;
|
|
38
|
+
Records?: PreviewRecordOutput[];
|
|
39
|
+
}
|
|
40
|
+
declare class SchemaPreviewObjectInput {
|
|
41
|
+
SourceObjectName: string;
|
|
42
|
+
SchemaName: string;
|
|
43
|
+
TableName: string;
|
|
44
|
+
EntityName: string;
|
|
45
|
+
}
|
|
46
|
+
declare class SchemaPreviewFileOutput {
|
|
47
|
+
FilePath: string;
|
|
48
|
+
Content: string;
|
|
49
|
+
Description: string;
|
|
50
|
+
}
|
|
51
|
+
declare class SchemaPreviewOutput {
|
|
52
|
+
Success: boolean;
|
|
53
|
+
Message: string;
|
|
54
|
+
Files?: SchemaPreviewFileOutput[];
|
|
55
|
+
Warnings?: string[];
|
|
56
|
+
}
|
|
57
|
+
declare class DefaultFieldMappingOutput {
|
|
58
|
+
SourceFieldName: string;
|
|
59
|
+
DestinationFieldName: string;
|
|
60
|
+
IsKeyField?: boolean;
|
|
61
|
+
}
|
|
62
|
+
declare class DefaultObjectConfigOutput {
|
|
63
|
+
SourceObjectName: string;
|
|
64
|
+
TargetTableName: string;
|
|
65
|
+
TargetEntityName: string;
|
|
66
|
+
SyncEnabled: boolean;
|
|
67
|
+
FieldMappings: DefaultFieldMappingOutput[];
|
|
68
|
+
}
|
|
69
|
+
declare class DefaultConfigOutput {
|
|
70
|
+
Success: boolean;
|
|
71
|
+
Message: string;
|
|
72
|
+
DefaultSchemaName?: string;
|
|
73
|
+
DefaultObjects?: DefaultObjectConfigOutput[];
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* GraphQL resolver for integration discovery operations.
|
|
77
|
+
* Provides endpoints to test connections, discover objects, and discover fields
|
|
78
|
+
* on external systems via their registered connectors.
|
|
79
|
+
*/
|
|
80
|
+
export declare class IntegrationDiscoveryResolver extends ResolverBase {
|
|
81
|
+
/**
|
|
82
|
+
* Discovers available objects/tables in the external system.
|
|
83
|
+
*/
|
|
84
|
+
IntegrationDiscoverObjects(companyIntegrationID: string, ctx: AppContext): Promise<DiscoverObjectsOutput>;
|
|
85
|
+
/**
|
|
86
|
+
* Discovers fields on a specific external object.
|
|
87
|
+
*/
|
|
88
|
+
IntegrationDiscoverFields(companyIntegrationID: string, objectName: string, ctx: AppContext): Promise<DiscoverFieldsOutput>;
|
|
89
|
+
/**
|
|
90
|
+
* Tests connectivity to the external system.
|
|
91
|
+
*/
|
|
92
|
+
IntegrationTestConnection(companyIntegrationID: string, ctx: AppContext): Promise<ConnectionTestOutput>;
|
|
93
|
+
/**
|
|
94
|
+
* Returns the connector's default configuration for quick setup.
|
|
95
|
+
* Not all connectors provide defaults — returns Success: false if unavailable.
|
|
96
|
+
*/
|
|
97
|
+
IntegrationGetDefaultConfig(companyIntegrationID: string, ctx: AppContext): Promise<DefaultConfigOutput>;
|
|
98
|
+
/**
|
|
99
|
+
* Generates a DDL preview for creating tables from discovered external objects.
|
|
100
|
+
* Introspects the source schema and runs SchemaBuilder to produce migration SQL.
|
|
101
|
+
*/
|
|
102
|
+
IntegrationSchemaPreview(companyIntegrationID: string, objects: SchemaPreviewObjectInput[], platform: string, ctx: AppContext): Promise<SchemaPreviewOutput>;
|
|
103
|
+
/**
|
|
104
|
+
* Fetches a small sample of records from an external object for preview purposes.
|
|
105
|
+
* Uses the connector's FetchChanges with a small batch size and no watermark.
|
|
106
|
+
*/
|
|
107
|
+
IntegrationPreviewData(companyIntegrationID: string, objectName: string, limit: number, ctx: AppContext): Promise<PreviewDataOutput>;
|
|
108
|
+
private buildTargetConfigs;
|
|
109
|
+
private getAuthenticatedUser;
|
|
110
|
+
/**
|
|
111
|
+
* Loads the CompanyIntegration + its parent Integration, then resolves the
|
|
112
|
+
* appropriate connector via ConnectorFactory.
|
|
113
|
+
*
|
|
114
|
+
* NOTE: Entity objects loaded here come from the MJServer's copy of core-entities.
|
|
115
|
+
* The integration-engine package may resolve its own copy of core-entities, causing
|
|
116
|
+
* TypeScript nominal type mismatches. At runtime the objects are structurally identical,
|
|
117
|
+
* so we cast through `unknown` at the boundary calls.
|
|
118
|
+
*/
|
|
119
|
+
private resolveConnector;
|
|
120
|
+
private handleDiscoveryError;
|
|
121
|
+
}
|
|
122
|
+
export {};
|
|
123
|
+
//# sourceMappingURL=IntegrationDiscoveryResolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IntegrationDiscoveryResolver.d.ts","sourceRoot":"","sources":["../../src/resolvers/IntegrationDiscoveryResolver.ts"],"names":[],"mappings":"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"}
|