@memberjunction/server 6.1.5 → 6.1.6
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/dist/.tsbuildinfo +1 -1
- package/dist/agentSessions/SessionManager.d.ts +5 -2
- package/dist/agentSessions/SessionManager.d.ts.map +1 -1
- package/dist/agentSessions/SessionManager.js +17 -8
- package/dist/agentSessions/SessionManager.js.map +1 -1
- package/dist/agentSessions/SessionRunIDVerifier.d.ts +63 -0
- package/dist/agentSessions/SessionRunIDVerifier.d.ts.map +1 -0
- package/dist/agentSessions/SessionRunIDVerifier.js +129 -0
- package/dist/agentSessions/SessionRunIDVerifier.js.map +1 -0
- package/dist/agentSessions/index.d.ts +1 -0
- package/dist/agentSessions/index.d.ts.map +1 -1
- package/dist/agentSessions/index.js +1 -0
- package/dist/agentSessions/index.js.map +1 -1
- package/dist/auth/actionAuthorization.d.ts +40 -0
- package/dist/auth/actionAuthorization.d.ts.map +1 -0
- package/dist/auth/actionAuthorization.js +94 -0
- package/dist/auth/actionAuthorization.js.map +1 -0
- package/dist/auth/exampleNewUserSubClass.js +2 -1
- package/dist/auth/exampleNewUserSubClass.js.map +1 -1
- package/dist/auth/magicLink/MagicLinkService.d.ts.map +1 -1
- package/dist/auth/magicLink/MagicLinkService.js +6 -3
- package/dist/auth/magicLink/MagicLinkService.js.map +1 -1
- package/dist/auth/newUsers.d.ts.map +1 -1
- package/dist/auth/newUsers.js +15 -11
- package/dist/auth/newUsers.js.map +1 -1
- package/dist/context.d.ts +6 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +13 -11
- package/dist/context.js.map +1 -1
- package/dist/generated/graphql-schemas/__mj.d.ts.map +1 -1
- package/dist/generated/graphql-schemas/__mj.js +3417 -3428
- package/dist/generated/graphql-schemas/__mj.js.map +1 -1
- package/dist/generic/CacheInvalidationResolver.d.ts +44 -8
- package/dist/generic/CacheInvalidationResolver.d.ts.map +1 -1
- package/dist/generic/CacheInvalidationResolver.js +59 -19
- package/dist/generic/CacheInvalidationResolver.js.map +1 -1
- package/dist/generic/ResolverBase.d.ts +95 -11
- package/dist/generic/ResolverBase.d.ts.map +1 -1
- package/dist/generic/ResolverBase.js +186 -76
- package/dist/generic/ResolverBase.js.map +1 -1
- package/dist/generic/RunViewResolver.d.ts.map +1 -1
- package/dist/generic/RunViewResolver.js +12 -0
- package/dist/generic/RunViewResolver.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -1
- package/dist/index.js.map +1 -1
- package/dist/isolatedProvider.d.ts +20 -0
- package/dist/isolatedProvider.d.ts.map +1 -0
- package/dist/isolatedProvider.js +22 -0
- package/dist/isolatedProvider.js.map +1 -0
- package/dist/multiTenancy/index.d.ts.map +1 -1
- package/dist/multiTenancy/index.js +22 -2
- package/dist/multiTenancy/index.js.map +1 -1
- package/dist/realtimeWidget/widgetGuestElevation.d.ts +4 -2
- package/dist/realtimeWidget/widgetGuestElevation.d.ts.map +1 -1
- package/dist/realtimeWidget/widgetGuestElevation.js +4 -2
- package/dist/realtimeWidget/widgetGuestElevation.js.map +1 -1
- package/dist/resolvers/ActionResolver.d.ts +31 -5
- package/dist/resolvers/ActionResolver.d.ts.map +1 -1
- package/dist/resolvers/ActionResolver.js +75 -14
- package/dist/resolvers/ActionResolver.js.map +1 -1
- package/dist/resolvers/AdhocQueryResolver.d.ts +28 -0
- package/dist/resolvers/AdhocQueryResolver.d.ts.map +1 -1
- package/dist/resolvers/AdhocQueryResolver.js +46 -0
- package/dist/resolvers/AdhocQueryResolver.js.map +1 -1
- package/dist/resolvers/DatasetResolver.d.ts +24 -3
- package/dist/resolvers/DatasetResolver.d.ts.map +1 -1
- package/dist/resolvers/DatasetResolver.js +57 -8
- package/dist/resolvers/DatasetResolver.js.map +1 -1
- package/dist/resolvers/EntityRecordNameResolver.d.ts +8 -23
- package/dist/resolvers/EntityRecordNameResolver.d.ts.map +1 -1
- package/dist/resolvers/EntityRecordNameResolver.js +11 -48
- package/dist/resolvers/EntityRecordNameResolver.js.map +1 -1
- package/dist/resolvers/FetchEntityVectorsResolver.js +2 -2
- package/dist/resolvers/FetchEntityVectorsResolver.js.map +1 -1
- package/dist/resolvers/GetDataContextDataResolver.d.ts +33 -7
- package/dist/resolvers/GetDataContextDataResolver.d.ts.map +1 -1
- package/dist/resolvers/GetDataContextDataResolver.js +117 -38
- package/dist/resolvers/GetDataContextDataResolver.js.map +1 -1
- package/dist/resolvers/GetDataResolver.d.ts.map +1 -1
- package/dist/resolvers/GetDataResolver.js +13 -1
- package/dist/resolvers/GetDataResolver.js.map +1 -1
- package/dist/resolvers/QuerySystemUserResolver.d.ts.map +1 -1
- package/dist/resolvers/QuerySystemUserResolver.js +2 -1
- package/dist/resolvers/QuerySystemUserResolver.js.map +1 -1
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts +39 -16
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
- package/dist/resolvers/RealtimeClientSessionResolver.js +84 -38
- package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
- package/dist/resolvers/RemoteBrowserActionResolver.d.ts +2 -0
- package/dist/resolvers/RemoteBrowserActionResolver.d.ts.map +1 -1
- package/dist/resolvers/RemoteBrowserActionResolver.js +5 -1
- package/dist/resolvers/RemoteBrowserActionResolver.js.map +1 -1
- package/dist/resolvers/RunTemplateResolver.d.ts.map +1 -1
- package/dist/resolvers/RunTemplateResolver.js +12 -11
- package/dist/resolvers/RunTemplateResolver.js.map +1 -1
- package/dist/resolvers/SearchKnowledgeResolver.d.ts +1 -0
- package/dist/resolvers/SearchKnowledgeResolver.d.ts.map +1 -1
- package/dist/resolvers/SearchKnowledgeResolver.js +5 -0
- package/dist/resolvers/SearchKnowledgeResolver.js.map +1 -1
- package/dist/resolvers/SearchKnowledgeSystemUserResolver.d.ts.map +1 -1
- package/dist/resolvers/SearchKnowledgeSystemUserResolver.js +1 -0
- package/dist/resolvers/SearchKnowledgeSystemUserResolver.js.map +1 -1
- package/dist/resolvers/SyncDataResolver.d.ts.map +1 -1
- package/dist/resolvers/SyncDataResolver.js +6 -2
- package/dist/resolvers/SyncDataResolver.js.map +1 -1
- package/dist/resolvers/VectorizeEntityResolver.d.ts +1 -1
- package/dist/resolvers/VectorizeEntityResolver.d.ts.map +1 -1
- package/dist/resolvers/VectorizeEntityResolver.js +14 -10
- package/dist/resolvers/VectorizeEntityResolver.js.map +1 -1
- package/dist/rest/ViewOperationsHandler.d.ts +3 -1
- package/dist/rest/ViewOperationsHandler.d.ts.map +1 -1
- package/dist/rest/ViewOperationsHandler.js +29 -17
- package/dist/rest/ViewOperationsHandler.js.map +1 -1
- package/dist/services/TaskGraphActionRunner.d.ts +8 -0
- package/dist/services/TaskGraphActionRunner.d.ts.map +1 -1
- package/dist/services/TaskGraphActionRunner.js +27 -1
- package/dist/services/TaskGraphActionRunner.js.map +1 -1
- package/package.json +92 -92
- package/src/__tests__/ActionResolver.authorization.test.ts +353 -0
- package/src/__tests__/AdhocQueryResolver.bugs.test.ts +4 -2
- package/src/__tests__/AdhocQueryResolver.sqlAuthorizer.test.ts +104 -0
- package/src/__tests__/DatasetResolver.itemFilters.test.ts +201 -0
- package/src/__tests__/EntityRecordNameResolver.fieldSecurity.test.ts +27 -72
- package/src/__tests__/EntityRecordNameResolver.rowSecurity.test.ts +152 -0
- package/src/__tests__/GetDataContextDataResolver.sqlItems.test.ts +416 -0
- package/src/__tests__/ListOperationsResolver.adhocScreen.test.ts +137 -0
- package/src/__tests__/RealtimeClientSessionResolver.configTamper.test.ts +383 -0
- package/src/__tests__/RealtimeClientSessionResolver.test.ts +106 -41
- package/src/__tests__/RemoteBrowserActionResolver.goalRunLink.test.ts +129 -0
- package/src/__tests__/ResolverBase.adhocReadScope.test.ts +227 -0
- package/src/__tests__/ResolverBase.aggregateScreen.test.ts +174 -0
- package/src/__tests__/ResolverBase.balancedClause.test.ts +155 -0
- package/src/__tests__/ResolverBase.clauseUnscopedRead.test.ts +127 -0
- package/src/__tests__/ResolverBase.filterEscaping.test.ts +24 -2
- package/src/__tests__/ResolverBase.isaPromotionCreate.test.ts +412 -0
- package/src/__tests__/RunTemplateResolver.test.ts +132 -0
- package/src/__tests__/RunViewResolver.cacheCheckScreen.test.ts +165 -0
- package/src/__tests__/SessionManager.test.ts +94 -17
- package/src/__tests__/SessionRunIDVerifier.test.ts +251 -0
- package/src/__tests__/TaskGraphActionRunner.durablePayload.test.ts +2 -0
- package/src/__tests__/TaskGraphActionRunner.storableOutputs.test.ts +76 -0
- package/src/__tests__/UpdateMJDataContextItem.oldValues.test.ts +220 -0
- package/src/__tests__/VectorizeEntityResolver.test.ts +106 -0
- package/src/__tests__/ViewOperationsHandler.clauseScreen.test.ts +157 -0
- package/src/__tests__/actionAuthorization.test.ts +130 -0
- package/src/__tests__/cacheInvalidationRecordData.test.ts +64 -0
- package/src/__tests__/isolatedProviderTransactions.test.ts +169 -0
- package/src/__tests__/magicLinkService.consume.test.ts +6 -0
- package/src/__tests__/magicLinkService.provisionLog.test.ts +5 -0
- package/src/__tests__/multiTenancy.postgresRewrite.test.ts +181 -0
- package/src/__tests__/multiTenancy.security.test.ts +51 -0
- package/src/__tests__/multiTenancy.test.ts +1 -1
- package/src/__tests__/newUsers.test.ts +62 -5
- package/src/agentSessions/SessionManager.ts +23 -25
- package/src/agentSessions/SessionRunIDVerifier.ts +171 -0
- package/src/agentSessions/index.ts +1 -0
- package/src/auth/actionAuthorization.ts +119 -0
- package/src/auth/exampleNewUserSubClass.ts +2 -2
- package/src/auth/magicLink/MagicLinkService.ts +6 -3
- package/src/auth/newUsers.ts +15 -11
- package/src/context.ts +14 -10
- package/src/generated/graphql-schemas/__mj.ts +3417 -3428
- package/src/generic/CacheInvalidationResolver.ts +74 -19
- package/src/generic/ResolverBase.ts +207 -80
- package/src/generic/RunViewResolver.ts +17 -0
- package/src/index.ts +9 -1
- package/src/isolatedProvider.ts +22 -0
- package/src/multiTenancy/index.ts +24 -2
- package/src/realtimeWidget/widgetGuestElevation.ts +4 -2
- package/src/resolvers/ActionResolver.ts +84 -21
- package/src/resolvers/AdhocQueryResolver.ts +49 -1
- package/src/resolvers/DatasetResolver.ts +70 -10
- package/src/resolvers/EntityRecordNameResolver.ts +11 -52
- package/src/resolvers/FetchEntityVectorsResolver.ts +2 -2
- package/src/resolvers/GetDataContextDataResolver.ts +139 -41
- package/src/resolvers/GetDataResolver.ts +14 -1
- package/src/resolvers/QuerySystemUserResolver.ts +2 -1
- package/src/resolvers/RealtimeClientSessionResolver.ts +103 -42
- package/src/resolvers/RemoteBrowserActionResolver.ts +11 -1
- package/src/resolvers/RunTemplateResolver.ts +13 -12
- package/src/resolvers/SearchKnowledgeResolver.ts +4 -0
- package/src/resolvers/SearchKnowledgeSystemUserResolver.ts +1 -0
- package/src/resolvers/SyncDataResolver.ts +6 -2
- package/src/resolvers/VectorizeEntityResolver.ts +16 -11
- package/src/resolvers/__tests__/GetDataResolver.validation.test.ts +95 -0
- package/src/rest/ViewOperationsHandler.ts +37 -18
- package/src/services/TaskGraphActionRunner.ts +29 -1
|
@@ -82,6 +82,40 @@ export declare function cacheInvalidationFilter(data: {
|
|
|
82
82
|
payload: CacheInvalidationPayload;
|
|
83
83
|
context: CacheInvalidationFilterContext | undefined;
|
|
84
84
|
}): boolean;
|
|
85
|
+
/** The part of a permission row and of a user this module reads, so the rule can be tested on plain objects. */
|
|
86
|
+
export interface ReadPermissionRow {
|
|
87
|
+
RoleID: string;
|
|
88
|
+
CanRead: boolean | null;
|
|
89
|
+
/** `Deny` rows subtract; they never carry the read the rule looks at. */
|
|
90
|
+
IsDeny?: boolean;
|
|
91
|
+
Type?: string | null;
|
|
92
|
+
ReadRLSFilterID: string | null;
|
|
93
|
+
}
|
|
94
|
+
export interface RoleHolder {
|
|
95
|
+
UserRoles?: ReadonlyArray<{
|
|
96
|
+
RoleID: string;
|
|
97
|
+
}> | null;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Is this user's read of the entity row-filtered? True when every read the user holds on the entity comes through a permission
|
|
101
|
+
* row that carries a `ReadRLSFilterID`: there is a row-level security filter between them and the rows, so a record's key, its
|
|
102
|
+
* existence and when it changed are not theirs to learn unless the row passes the filter — which a subscription filter cannot
|
|
103
|
+
* evaluate per event. False when any of their read rows is unfiltered (they could read the row anyway), and false when they hold
|
|
104
|
+
* no read at all (the entity-level filter has already withheld the event).
|
|
105
|
+
*
|
|
106
|
+
* The same in-memory match `GetUserPermisions` does, with no I/O, so it can run per subscriber per event.
|
|
107
|
+
*/
|
|
108
|
+
export declare function ReadIsRowFiltered(entity: {
|
|
109
|
+
Permissions: ReadonlyArray<ReadPermissionRow>;
|
|
110
|
+
}, user: RoleHolder): boolean;
|
|
111
|
+
/**
|
|
112
|
+
* The event as one subscriber may see it. A subscriber whose read of the entity is row-filtered gets the entity, the action and
|
|
113
|
+
* the time, and neither the key nor the row: "something in this entity changed", which the client already takes as a
|
|
114
|
+
* whole-entity invalidation (a null key on `remote-invalidate`). Everyone else gets the event as published.
|
|
115
|
+
*/
|
|
116
|
+
export declare function ShapeCacheInvalidationEvent(payload: CacheInvalidationPayload, user: RoleHolder | undefined, entity: {
|
|
117
|
+
Permissions: ReadonlyArray<ReadPermissionRow>;
|
|
118
|
+
} | null | undefined): CacheInvalidationNotification;
|
|
85
119
|
export declare class CacheInvalidationResolver {
|
|
86
120
|
/**
|
|
87
121
|
* Subscription that broadcasts cache invalidation events to connected clients, so cross-server
|
|
@@ -103,14 +137,16 @@ export declare class CacheInvalidationResolver {
|
|
|
103
137
|
* its stable key, and every time it changes; across entities it learns the cadence and volume
|
|
104
138
|
* of another tenant's activity.
|
|
105
139
|
*
|
|
106
|
-
* The key is kept
|
|
107
|
-
* told about (see `ResolveEntityEventKey` in @memberjunction/core)
|
|
108
|
-
*
|
|
109
|
-
* hottest write paths.
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
140
|
+
* The key is kept for a subscriber who could read the row anyway, because consumers need it to
|
|
141
|
+
* re-read the record they were told about (see `ResolveEntityEventKey` in @memberjunction/core),
|
|
142
|
+
* and the coarse "something in this entity changed" forces whole-entity invalidation on the
|
|
143
|
+
* hottest write paths. It is withheld, with the row, from a subscriber whose every read of the
|
|
144
|
+
* entity goes through a row-level security filter ({@link ReadIsRowFiltered}): a filter the
|
|
145
|
+
* subscription cannot evaluate per event stands between them and the row, so they learn only
|
|
146
|
+
* that a row of the entity changed, and their caches refresh the entity as a whole. That is the
|
|
147
|
+
* same in-memory role match as the entity-level filter, once more per subscriber per event.
|
|
113
148
|
*/
|
|
114
|
-
cacheInvalidation(
|
|
149
|
+
cacheInvalidation(// case-violation-ok-legacy-back-compat: the property name is the GraphQL schema field name — renaming it breaks every client query
|
|
150
|
+
payload: CacheInvalidationPayload, context: CacheInvalidationFilterContext | undefined): CacheInvalidationNotification;
|
|
115
151
|
}
|
|
116
152
|
//# sourceMappingURL=CacheInvalidationResolver.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CacheInvalidationResolver.d.ts","sourceRoot":"","sources":["../../src/generic/CacheInvalidationResolver.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,wBAAwB,uBAAuB,CAAC;AAS7D;;;;;;;;;GASG;AACH,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,GAAG,IAAI,GAAG,IAAI,CASjG;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAIlE;AAED,qBACa,6BAA6B;IAEtC,UAAU,EAAG,MAAM,CAAC;IAGpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAG1B,MAAM,EAAG,MAAM,CAAC;IAGhB,cAAc,EAAG,MAAM,CAAC;IAGxB,SAAS,EAAG,IAAI,CAAC;IAGjB,eAAe,CAAC,EAAE,MAAM,CAAC;IAGzB,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,MAAM,WAAW,wBAAwB;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,IAAI,CAAC;IAChB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,8BAA8B;IAC3C,WAAW,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CAC1C;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE;IAC1C,OAAO,EAAE,wBAAwB,CAAC;IAClC,OAAO,EAAE,8BAA8B,GAAG,SAAS,CAAC;CACvD,GAAG,OAAO,CA2BV;AAED,qBACa,yBAAyB;IAClC
|
|
1
|
+
{"version":3,"file":"CacheInvalidationResolver.d.ts","sourceRoot":"","sources":["../../src/generic/CacheInvalidationResolver.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,wBAAwB,uBAAuB,CAAC;AAS7D;;;;;;;;;GASG;AACH,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,GAAG,IAAI,GAAG,IAAI,CASjG;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAIlE;AAED,qBACa,6BAA6B;IAEtC,UAAU,EAAG,MAAM,CAAC;IAGpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAG1B,MAAM,EAAG,MAAM,CAAC;IAGhB,cAAc,EAAG,MAAM,CAAC;IAGxB,SAAS,EAAG,IAAI,CAAC;IAGjB,eAAe,CAAC,EAAE,MAAM,CAAC;IAGzB,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,MAAM,WAAW,wBAAwB;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,IAAI,CAAC;IAChB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,8BAA8B;IAC3C,WAAW,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CAC1C;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE;IAC1C,OAAO,EAAE,wBAAwB,CAAC;IAClC,OAAO,EAAE,8BAA8B,GAAG,SAAS,CAAC;CACvD,GAAG,OAAO,CA2BV;AAED,gHAAgH;AAChH,MAAM,WAAW,iBAAiB;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACxB,yEAAyE;IACzE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AACD,MAAM,WAAW,UAAU;IACvB,SAAS,CAAC,EAAE,aAAa,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,IAAI,CAAC;CACxD;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE;IAAE,WAAW,EAAE,aAAa,CAAC,iBAAiB,CAAC,CAAA;CAAE,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAYtH;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CACvC,OAAO,EAAE,wBAAwB,EACjC,IAAI,EAAE,UAAU,GAAG,SAAS,EAC5B,MAAM,EAAE;IAAE,WAAW,EAAE,aAAa,CAAC,iBAAiB,CAAC,CAAA;CAAE,GAAG,IAAI,GAAG,SAAS,GAC7E,6BAA6B,CAW/B;AAED,qBACa,yBAAyB;IAClC;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4BG;IAMH,iBAAiB,CAAG,mIAAmI;IAC3I,OAAO,EAAE,wBAAwB,EAClC,OAAO,EAAE,8BAA8B,GAAG,SAAS,GAC3D,6BAA6B;CAMnC"}
|
|
@@ -10,7 +10,7 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
10
10
|
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
11
11
|
return function (target, key) { decorator(target, key, paramIndex); }
|
|
12
12
|
};
|
|
13
|
-
import { Field, ObjectType, Resolver, Root, Subscription } from 'type-graphql';
|
|
13
|
+
import { Ctx, Field, ObjectType, Resolver, Root, Subscription } from 'type-graphql';
|
|
14
14
|
import { Metadata } from '@memberjunction/core';
|
|
15
15
|
export const CACHE_INVALIDATION_TOPIC = 'CACHE_INVALIDATION';
|
|
16
16
|
/**
|
|
@@ -137,6 +137,49 @@ export function cacheInvalidationFilter(data) {
|
|
|
137
137
|
}
|
|
138
138
|
return entity.GetUserPermisions(user).CanRead;
|
|
139
139
|
}
|
|
140
|
+
/**
|
|
141
|
+
* Is this user's read of the entity row-filtered? True when every read the user holds on the entity comes through a permission
|
|
142
|
+
* row that carries a `ReadRLSFilterID`: there is a row-level security filter between them and the rows, so a record's key, its
|
|
143
|
+
* existence and when it changed are not theirs to learn unless the row passes the filter — which a subscription filter cannot
|
|
144
|
+
* evaluate per event. False when any of their read rows is unfiltered (they could read the row anyway), and false when they hold
|
|
145
|
+
* no read at all (the entity-level filter has already withheld the event).
|
|
146
|
+
*
|
|
147
|
+
* The same in-memory match `GetUserPermisions` does, with no I/O, so it can run per subscriber per event.
|
|
148
|
+
*/
|
|
149
|
+
export function ReadIsRowFiltered(entity, user) {
|
|
150
|
+
const roles = new Set((user.UserRoles ?? []).map((role) => (role.RoleID ?? '').trim().toLowerCase()));
|
|
151
|
+
let filteredReads = 0;
|
|
152
|
+
for (const row of entity.Permissions) {
|
|
153
|
+
if (!row.CanRead)
|
|
154
|
+
continue;
|
|
155
|
+
const isDeny = row.IsDeny ?? (row.Type ?? 'Allow').trim().toLowerCase() === 'deny';
|
|
156
|
+
if (isDeny)
|
|
157
|
+
continue;
|
|
158
|
+
if (!roles.has((row.RoleID ?? '').trim().toLowerCase()))
|
|
159
|
+
continue;
|
|
160
|
+
if (!row.ReadRLSFilterID)
|
|
161
|
+
return false;
|
|
162
|
+
filteredReads += 1;
|
|
163
|
+
}
|
|
164
|
+
return filteredReads > 0;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* The event as one subscriber may see it. A subscriber whose read of the entity is row-filtered gets the entity, the action and
|
|
168
|
+
* the time, and neither the key nor the row: "something in this entity changed", which the client already takes as a
|
|
169
|
+
* whole-entity invalidation (a null key on `remote-invalidate`). Everyone else gets the event as published.
|
|
170
|
+
*/
|
|
171
|
+
export function ShapeCacheInvalidationEvent(payload, user, entity) {
|
|
172
|
+
const withholdKey = !!user && !!entity && ReadIsRowFiltered(entity, user);
|
|
173
|
+
return {
|
|
174
|
+
EntityName: payload.entityName,
|
|
175
|
+
PrimaryKeyValues: withholdKey ? undefined : (payload.primaryKeyValues ?? undefined),
|
|
176
|
+
Action: payload.action,
|
|
177
|
+
SourceServerID: payload.sourceServerId,
|
|
178
|
+
Timestamp: payload.timestamp,
|
|
179
|
+
OriginSessionID: payload.originSessionId ?? undefined,
|
|
180
|
+
RecordData: withholdKey ? undefined : (payload.recordData ?? undefined),
|
|
181
|
+
};
|
|
182
|
+
}
|
|
140
183
|
let CacheInvalidationResolver = class CacheInvalidationResolver {
|
|
141
184
|
/**
|
|
142
185
|
* Subscription that broadcasts cache invalidation events to connected clients, so cross-server
|
|
@@ -158,24 +201,20 @@ let CacheInvalidationResolver = class CacheInvalidationResolver {
|
|
|
158
201
|
* its stable key, and every time it changes; across entities it learns the cadence and volume
|
|
159
202
|
* of another tenant's activity.
|
|
160
203
|
*
|
|
161
|
-
* The key is kept
|
|
162
|
-
* told about (see `ResolveEntityEventKey` in @memberjunction/core)
|
|
163
|
-
*
|
|
164
|
-
* hottest write paths.
|
|
165
|
-
*
|
|
166
|
-
*
|
|
167
|
-
*
|
|
204
|
+
* The key is kept for a subscriber who could read the row anyway, because consumers need it to
|
|
205
|
+
* re-read the record they were told about (see `ResolveEntityEventKey` in @memberjunction/core),
|
|
206
|
+
* and the coarse "something in this entity changed" forces whole-entity invalidation on the
|
|
207
|
+
* hottest write paths. It is withheld, with the row, from a subscriber whose every read of the
|
|
208
|
+
* entity goes through a row-level security filter ({@link ReadIsRowFiltered}): a filter the
|
|
209
|
+
* subscription cannot evaluate per event stands between them and the row, so they learn only
|
|
210
|
+
* that a row of the entity changed, and their caches refresh the entity as a whole. That is the
|
|
211
|
+
* same in-memory role match as the entity-level filter, once more per subscriber per event.
|
|
168
212
|
*/
|
|
169
|
-
cacheInvalidation(payload) {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
SourceServerID: payload.sourceServerId,
|
|
175
|
-
Timestamp: payload.timestamp,
|
|
176
|
-
OriginSessionID: payload.originSessionId ?? undefined,
|
|
177
|
-
RecordData: payload.recordData ?? undefined,
|
|
178
|
-
};
|
|
213
|
+
cacheInvalidation(payload, context) {
|
|
214
|
+
const user = context?.userPayload?.userRecord;
|
|
215
|
+
// The same server-wide metadata the filter read; an entity unknown here was delivered whole by the filter's own choice
|
|
216
|
+
const entity = payload?.entityName ? new Metadata().EntityByName(payload.entityName) : null; // global-provider-ok: subscription resolver — server-wide metadata, no request-scoped provider exists here
|
|
217
|
+
return ShapeCacheInvalidationEvent(payload, user, entity);
|
|
179
218
|
}
|
|
180
219
|
};
|
|
181
220
|
__decorate([
|
|
@@ -184,8 +223,9 @@ __decorate([
|
|
|
184
223
|
filter: (data) => cacheInvalidationFilter(data),
|
|
185
224
|
}),
|
|
186
225
|
__param(0, Root()),
|
|
226
|
+
__param(1, Ctx()),
|
|
187
227
|
__metadata("design:type", Function),
|
|
188
|
-
__metadata("design:paramtypes", [Object]),
|
|
228
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
189
229
|
__metadata("design:returntype", CacheInvalidationNotification)
|
|
190
230
|
], CacheInvalidationResolver.prototype, "cacheInvalidation", null);
|
|
191
231
|
CacheInvalidationResolver = __decorate([
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CacheInvalidationResolver.js","sourceRoot":"","sources":["../../src/generic/CacheInvalidationResolver.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"CacheInvalidationResolver.js","sourceRoot":"","sources":["../../src/generic/CacheInvalidationResolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -99,13 +99,16 @@ export declare class ResolverBase {
|
|
|
99
99
|
* @param dataObject - The data object containing field values
|
|
100
100
|
* @param encryptionEngine - Optional encryption engine for re-encryption (lazy loaded if needed)
|
|
101
101
|
* @param contextUser - User context for encryption operations
|
|
102
|
+
* @param fieldKey - What the object's keys are: field CodeNames (GraphQL transport rows, the
|
|
103
|
+
* default) or field Names (raw provider rows, such as dataset item results)
|
|
102
104
|
* @returns The filtered data object
|
|
103
105
|
*/
|
|
104
|
-
protected FilterEncryptedFieldsForAPI(entityName: string, dataObject: Record<string, unknown>, contextUser: UserInfo, provider?: IMetadataProvider): Promise<Record<string, unknown>>;
|
|
106
|
+
protected FilterEncryptedFieldsForAPI(entityName: string, dataObject: Record<string, unknown>, contextUser: UserInfo, provider?: IMetadataProvider, fieldKey?: 'CodeName' | 'Name'): Promise<Record<string, unknown>>;
|
|
105
107
|
/**
|
|
106
|
-
* Filters encrypted fields for an array of data objects
|
|
108
|
+
* Filters encrypted fields for an array of data objects. `fieldKey` is as for
|
|
109
|
+
* {@link FilterEncryptedFieldsForAPI}.
|
|
107
110
|
*/
|
|
108
|
-
protected ArrayFilterEncryptedFieldsForAPI(entityName: string, dataObjectArray: Record<string, unknown>[], contextUser: UserInfo, provider?: IMetadataProvider): Promise<Record<string, unknown>[]>;
|
|
111
|
+
protected ArrayFilterEncryptedFieldsForAPI(entityName: string, dataObjectArray: Record<string, unknown>[], contextUser: UserInfo, provider?: IMetadataProvider, fieldKey?: 'CodeName' | 'Name'): Promise<Record<string, unknown>[]>;
|
|
109
112
|
/**
|
|
110
113
|
* Renders one `findBy` predicate value as the SQL literal text it will become inside the
|
|
111
114
|
* `ExtraFilter` that method builds.
|
|
@@ -163,13 +166,53 @@ export declare class ResolverBase {
|
|
|
163
166
|
* This screen uses `@memberjunction/sql-parser` (same wrap as EDS `assertReadOnlyClause`):
|
|
164
167
|
* wrap the fragment as a single SELECT, fail closed if it does not parse as a read, then
|
|
165
168
|
* allow a FROM only when it is an entity **BaseView**. Base tables (`Meeting`, `__mj.User`)
|
|
166
|
-
* and catalogs are rejected. Server-internal RunView callers
|
|
169
|
+
* and catalogs are rejected. Server-internal RunView callers get only the provider's
|
|
170
|
+
* statement-separator check, which cannot refuse a legitimate filter.
|
|
171
|
+
*
|
|
172
|
+
* The screen is `ClientClauseScreen` in `@memberjunction/generic-database-provider`, shared
|
|
173
|
+
* with the REST view routes, ad-hoc list sources, and the provider's saved-view checks.
|
|
174
|
+
*
|
|
175
|
+
* Before that parse, the fragment must be balanced on its own (`IsBalancedSQLFragment`). The
|
|
176
|
+
* provider and the tenant hook splice it inside parentheses and AND their own filters after
|
|
177
|
+
* it, so a fragment that closes those parentheses (`1=1) OR (1=1`) would leave row-level
|
|
178
|
+
* security, API-key row filters and tenant scope on one side of an OR the caller controls.
|
|
179
|
+
* The parse wraps the fragment in parentheses too, which is why it cannot catch this alone.
|
|
180
|
+
* A backslash inside a quoted string or identifier is refused as well: the parser reads `\'`
|
|
181
|
+
* inside a plain literal as an escaped quote, but SQL Server and PostgreSQL end the literal
|
|
182
|
+
* there, so the text after it could be code that the parse-based checks never saw.
|
|
167
183
|
*
|
|
168
184
|
* RLS is applied by RunView as an outer WHERE around the entity being queried, not compiled
|
|
169
|
-
* into the view
|
|
170
|
-
*
|
|
185
|
+
* into the view, and RunView removes denied fields from its own result only. A subquery reads a
|
|
186
|
+
* base view directly with neither, so the screen refuses one over any entity the user reads under
|
|
187
|
+
* a row filter or with denied fields (`ClientClauseScreen.AssertUnscopedRead`), the queried
|
|
188
|
+
* entity included.
|
|
189
|
+
*/
|
|
190
|
+
protected assertClientClauseUsesEntityBaseViews(clause: string | undefined | null, label: string, provider?: IMetadataProvider, user?: UserInfo, options?: {
|
|
191
|
+
LeaveUnparseableToProvider?: boolean;
|
|
192
|
+
}): void;
|
|
193
|
+
/**
|
|
194
|
+
* SECURITY — screen for a FULL client-supplied SQL statement (ad-hoc query path). In addition
|
|
195
|
+
* to the SELECT-only validation the caller performs, every table reference must resolve to an
|
|
196
|
+
* entity BaseView the acting user can read UNSCOPED. A reference is excluded only when it reads a
|
|
197
|
+
* CTE that is in scope there (`StatementRelation.IsCTEReference`): unqualified, declared by its
|
|
198
|
+
* own SELECT or an enclosing one, and matched by the dialect's identifier rules. A name reserved
|
|
199
|
+
* for the SQL parser is refused before parsing (`ClientClauseScreen.AssertNoIdentifierAliasNames`).
|
|
200
|
+
* Fails closed: no user, or an unresolvable reference, refuses.
|
|
201
|
+
*
|
|
202
|
+
* The references come from a walk of the whole parse tree
|
|
203
|
+
* (`ClientClauseScreen.CollectStatementReads`). The statement is refused when that walk does not
|
|
204
|
+
* account for every SELECT in the text, or when a FROM item names no table (a table function or
|
|
205
|
+
* a row list).
|
|
206
|
+
*
|
|
207
|
+
* Entity CanRead is not unscoped base-view read authority: RunView narrows a granted read with
|
|
208
|
+
* row-level security and denied-field projection, and raw SQL applies neither. Rather than try
|
|
209
|
+
* to rewrite arbitrary SQL (joins, CTEs) to compose that policy, this refuses any entity that
|
|
210
|
+
* carries a row filter or a denied field for the caller — those reads belong on RunView. For
|
|
211
|
+
* the remaining entities CanRead genuinely means "every row and field of the view".
|
|
171
212
|
*/
|
|
172
|
-
protected
|
|
213
|
+
protected assertFullQueryUsesReadableEntityViews(sqlText: string, provider: IMetadataProvider | undefined, user: UserInfo | undefined, label?: string): void;
|
|
214
|
+
/** Refuses an entity whose read is narrowed for this user; see `ClientClauseScreen.AssertUnscopedRead`. */
|
|
215
|
+
private assertUnscopedRead;
|
|
173
216
|
/**
|
|
174
217
|
* Applies {@link assertClientClauseUsesEntityBaseViews} to every client-supplied clause
|
|
175
218
|
* a view request can carry that is actually a SQL fragment. GraphQL entry points
|
|
@@ -191,18 +234,28 @@ export declare class ResolverBase {
|
|
|
191
234
|
* The single place that is not true is a field carrying `UserSearchParamFormatAPI`, whose
|
|
192
235
|
* admin-authored format may splice the term in unquoted; `createViewUserSearchSQL` re-applies
|
|
193
236
|
* `ValidateUserProvidedSQLClause` for exactly those entities.
|
|
237
|
+
*
|
|
238
|
+
* Each `Aggregates[].expression` gets the same screen, except that text the parser cannot read
|
|
239
|
+
* goes on to the provider, which refuses it per aggregate. The provider never runs the caller's
|
|
240
|
+
* aggregate text: it runs the SQL that `CheckAggregateExpression` rebuilds from a single
|
|
241
|
+
* aggregate call over the entity's columns, and refuses everything else per aggregate.
|
|
194
242
|
*/
|
|
195
243
|
protected screenClientViewClauses(clauses: {
|
|
196
244
|
extraFilter?: string | null;
|
|
197
245
|
orderBy?: string | null;
|
|
198
246
|
userSearchString?: string | null;
|
|
199
247
|
overrideExcludeFilter?: string | null;
|
|
200
|
-
|
|
201
|
-
|
|
248
|
+
aggregates?: AggregateExpression[] | null;
|
|
249
|
+
}, provider?: IMetadataProvider, user?: UserInfo): void;
|
|
250
|
+
/**
|
|
251
|
+
* True when a string literal or quoted identifier in `clause`, read the way the database reads
|
|
252
|
+
* it, contains a backslash (see {@link assertClientClauseUsesEntityBaseViews}).
|
|
253
|
+
*/
|
|
254
|
+
private hasBackslashInQuotes;
|
|
255
|
+
/** Write/DDL node walk shared with the clause screen; see `ClientClauseScreen.AstContainsWriteNode`. */
|
|
202
256
|
private astContainsWriteNode;
|
|
203
|
-
private static readonly WRITE_NODE_TYPES;
|
|
204
257
|
private dialectForProvider;
|
|
205
|
-
|
|
258
|
+
/** The entity base-view allow-list for a provider's entities. */
|
|
206
259
|
private entityBaseViewAllowList;
|
|
207
260
|
/**
|
|
208
261
|
* Optimized RunViewGenericInternal implementation with:
|
|
@@ -245,6 +298,32 @@ export declare class ResolverBase {
|
|
|
245
298
|
*/
|
|
246
299
|
protected PublishStatusUpdate(pubSub: PubSubEngine, sessionId: string, message: string | undefined, userPayload: UserPayload): void;
|
|
247
300
|
protected ListenForEntityMessages(entityObject: BaseEntity, pubSub: PubSubEngine, userPayload: UserPayload): void;
|
|
301
|
+
/**
|
|
302
|
+
* IS-A PROMOTION over the wire: an EXISTING parent record gaining a subtype — an Animal that is
|
|
303
|
+
* now also a Dog. It arrives as the CHILD's create mutation carrying the existing parent's
|
|
304
|
+
* primary key, because in IS-A the shared key is the relationship and the child has no key of
|
|
305
|
+
* its own to mint. `NewRecord()` has just reset the whole chain to "new", so left alone the
|
|
306
|
+
* parent would save as a CREATE: a second copy of a row that already exists (a unique-constraint
|
|
307
|
+
* violation at best, a silently duplicated parent at worst).
|
|
308
|
+
*
|
|
309
|
+
* When a child create carries a complete primary key, bind the new child to the existing parent
|
|
310
|
+
* row with `AttachToParent` (#3825): it loads the parent chain, so the parent saves as an UPDATE
|
|
311
|
+
* and only the child is INSERTed. A key that matches no row leaves the fresh chain exactly as
|
|
312
|
+
* `NewRecord()` built it — the ordinary whole-chain create. A non-IS-A entity, or a create with
|
|
313
|
+
* no key, never gets past the guards.
|
|
314
|
+
*
|
|
315
|
+
* @returns true when the child was attached to an existing parent row.
|
|
316
|
+
*/
|
|
317
|
+
protected attachToExistingParentIfPromotion(entityObject: BaseEntity, input: Record<string, unknown>): Promise<boolean>;
|
|
318
|
+
/**
|
|
319
|
+
* The entity's primary key as supplied on a mutation input, or null when any part of it is
|
|
320
|
+
* missing. Composite keys are all-or-nothing: a half-specified key identifies nothing. An empty
|
|
321
|
+
* string counts as missing, the same as null — it is never a valid key value, and a GUID or
|
|
322
|
+
* string key that is "" identifies no row, so the create proceeds as a whole-chain create rather
|
|
323
|
+
* than failing the lookup. A malformed non-empty key (e.g. a non-GUID for a uniqueidentifier)
|
|
324
|
+
* is NOT swallowed: the load throws and the mutation fails loudly.
|
|
325
|
+
*/
|
|
326
|
+
protected primaryKeyFromInput(entityInfo: EntityInfo, input: Record<string, unknown>): CompositeKey | null;
|
|
248
327
|
protected CreateRecord(entityName: string, input: any, provider: DatabaseProviderBase, userPayload: UserPayload, pubSub: PubSubEngine): Promise<any>;
|
|
249
328
|
protected BeforeCreate(provider: DatabaseProviderBase, input: any): Promise<boolean>;
|
|
250
329
|
protected AfterCreate(provider: DatabaseProviderBase, input: any): Promise<void>;
|
|
@@ -275,6 +354,11 @@ export declare class ResolverBase {
|
|
|
275
354
|
*
|
|
276
355
|
* Ordered so the boolean flag is evaluated last: the extra load lands only on entities that have
|
|
277
356
|
* the feature switched on, which is almost none of them.
|
|
357
|
+
*
|
|
358
|
+
* `MJ: Data Context Items` always loads from the database: its server class lets only an
|
|
359
|
+
* administrator save an item that holds SQL, and decides that from the item's `Type` and `SQL`.
|
|
360
|
+
* Hydrated from OldValues, a client could leave both out, and the stored procedure would keep the
|
|
361
|
+
* stored SQL item while the rule saw none. See {@link ENTITIES_THAT_ALWAYS_LOAD_STORED_ROW}.
|
|
278
362
|
*/
|
|
279
363
|
protected MustLoadTruthFromDatabase(entityInfo: EntityInfo, input: {
|
|
280
364
|
OldValues___?: Array<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ResolverBase.d.ts","sourceRoot":"","sources":["../../src/generic/ResolverBase.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,UAAU,EAEV,YAAY,EACZ,oBAAoB,EAEpB,UAAU,EACV,oBAAoB,EAEpB,iBAAiB,
|
|
1
|
+
{"version":3,"file":"ResolverBase.d.ts","sourceRoot":"","sources":["../../src/generic/ResolverBase.ts"],"names":[],"mappings":"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"}
|