@memberjunction/server 6.1.0-edge.5 → 6.1.0-edge.7
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 +30 -11
- package/dist/.tsbuildinfo +1 -1
- package/dist/agentSessions/SessionJanitor.js +2 -2
- package/dist/agentSessions/SessionJanitor.js.map +1 -1
- package/dist/auth/exampleNewUserSubClass.d.ts.map +1 -1
- package/dist/auth/exampleNewUserSubClass.js +9 -4
- package/dist/auth/exampleNewUserSubClass.js.map +1 -1
- package/dist/auth/magicLink/MagicLinkService.d.ts.map +1 -1
- package/dist/auth/magicLink/MagicLinkService.js +2 -8
- package/dist/auth/magicLink/MagicLinkService.js.map +1 -1
- package/dist/auth/newUsers.d.ts.map +1 -1
- package/dist/auth/newUsers.js +4 -12
- package/dist/auth/newUsers.js.map +1 -1
- package/dist/auth/principals.d.ts +92 -0
- package/dist/auth/principals.d.ts.map +1 -0
- package/dist/auth/principals.js +193 -0
- package/dist/auth/principals.js.map +1 -0
- package/dist/config.d.ts +106 -12
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +41 -4
- package/dist/config.js.map +1 -1
- package/dist/entitySubclasses/MJEntityPermissionEntityServer.server.d.ts +30 -0
- package/dist/entitySubclasses/MJEntityPermissionEntityServer.server.d.ts.map +1 -1
- package/dist/entitySubclasses/MJEntityPermissionEntityServer.server.js +58 -5
- package/dist/entitySubclasses/MJEntityPermissionEntityServer.server.js.map +1 -1
- package/dist/generated/graphql-schemas/__mj.d.ts +7607 -6853
- package/dist/generated/graphql-schemas/__mj.d.ts.map +1 -1
- package/dist/generated/graphql-schemas/__mj.js +25141 -21645
- package/dist/generated/graphql-schemas/__mj.js.map +1 -1
- package/dist/generic/ResolverBase.d.ts +152 -2
- package/dist/generic/ResolverBase.d.ts.map +1 -1
- package/dist/generic/ResolverBase.js +389 -10
- package/dist/generic/ResolverBase.js.map +1 -1
- package/dist/generic/RunViewResolver.d.ts.map +1 -1
- package/dist/generic/RunViewResolver.js +26 -2
- package/dist/generic/RunViewResolver.js.map +1 -1
- package/dist/generic/refusalExtensions.d.ts +52 -0
- package/dist/generic/refusalExtensions.d.ts.map +1 -0
- package/dist/generic/refusalExtensions.js +16 -0
- package/dist/generic/refusalExtensions.js.map +1 -0
- package/dist/index.d.ts +11 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +131 -93
- package/dist/index.js.map +1 -1
- package/dist/realtimeWidget/WidgetSessionService.d.ts.map +1 -1
- package/dist/realtimeWidget/WidgetSessionService.js +2 -12
- package/dist/realtimeWidget/WidgetSessionService.js.map +1 -1
- package/dist/realtimeWidget/visitorIdentity.d.ts.map +1 -1
- package/dist/realtimeWidget/visitorIdentity.js +20 -5
- package/dist/realtimeWidget/visitorIdentity.js.map +1 -1
- package/dist/resolvers/EntityRecordNameResolver.d.ts +34 -5
- package/dist/resolvers/EntityRecordNameResolver.d.ts.map +1 -1
- package/dist/resolvers/EntityRecordNameResolver.js +64 -7
- package/dist/resolvers/EntityRecordNameResolver.js.map +1 -1
- package/dist/resolvers/FileCategoryResolver.d.ts.map +1 -1
- package/dist/resolvers/FileCategoryResolver.js +1 -2
- package/dist/resolvers/FileCategoryResolver.js.map +1 -1
- package/dist/resolvers/IntegrationDiscoveryResolver.d.ts.map +1 -1
- package/dist/resolvers/IntegrationDiscoveryResolver.js +2 -0
- package/dist/resolvers/IntegrationDiscoveryResolver.js.map +1 -1
- package/dist/resolvers/QuerySystemUserResolver.js +1 -1
- package/dist/resolvers/QuerySystemUserResolver.js.map +1 -1
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts +10 -2
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
- package/dist/resolvers/RealtimeClientSessionResolver.js +80 -4
- package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
- package/dist/resolvers/RemoteBrowserActionResolver.d.ts +13 -8
- package/dist/resolvers/RemoteBrowserActionResolver.d.ts.map +1 -1
- package/dist/resolvers/RemoteBrowserActionResolver.js +45 -8
- package/dist/resolvers/RemoteBrowserActionResolver.js.map +1 -1
- package/dist/resolvers/SyncRolesUsersResolver.d.ts.map +1 -1
- package/dist/resolvers/SyncRolesUsersResolver.js +11 -2
- package/dist/resolvers/SyncRolesUsersResolver.js.map +1 -1
- package/dist/resolvers/UserViewResolver.d.ts.map +1 -1
- package/dist/resolvers/UserViewResolver.js +8 -4
- package/dist/resolvers/UserViewResolver.js.map +1 -1
- package/dist/rest/EntityCRUDHandler.d.ts +2 -1
- package/dist/rest/EntityCRUDHandler.d.ts.map +1 -1
- package/dist/rest/EntityCRUDHandler.js +3 -18
- package/dist/rest/EntityCRUDHandler.js.map +1 -1
- package/dist/rest/RESTEndpointHandler.d.ts +2 -1
- package/dist/rest/RESTEndpointHandler.d.ts.map +1 -1
- package/dist/rest/RESTEndpointHandler.js +3 -16
- package/dist/rest/RESTEndpointHandler.js.map +1 -1
- package/dist/rest/RealtimeSdpBrokerHandler.d.ts +23 -0
- package/dist/rest/RealtimeSdpBrokerHandler.d.ts.map +1 -0
- package/dist/rest/RealtimeSdpBrokerHandler.js +78 -0
- package/dist/rest/RealtimeSdpBrokerHandler.js.map +1 -0
- package/dist/serverExtensionReservedRoots.d.ts.map +1 -1
- package/dist/serverExtensionReservedRoots.js +2 -3
- package/dist/serverExtensionReservedRoots.js.map +1 -1
- package/package.json +92 -91
- package/src/__tests__/EntityCRUDHandler.test.ts +18 -5
- package/src/__tests__/EntityRecordNameResolver.fieldSecurity.test.ts +118 -0
- package/src/__tests__/RealtimeClientSessionResolver.test.ts +20 -0
- package/src/__tests__/RealtimeSdpBrokerHandler.test.ts +191 -0
- package/src/__tests__/RemoteBrowserAudioStream.test.ts +81 -2
- package/src/__tests__/ResolverBase.filterEscaping.test.ts +190 -3
- package/src/__tests__/ResolverBase.readableFieldsTransport.test.ts +106 -0
- package/src/__tests__/UserViewResolver.updateWhereClause.test.ts +114 -0
- package/src/__tests__/WidgetSessionService.test.ts +4 -1
- package/src/__tests__/generatedGraphQLSchema.structural.test.ts +46 -0
- package/src/__tests__/newUserRolesDefault.test.ts +81 -0
- package/src/__tests__/newUsers.test.ts +36 -14
- package/src/__tests__/principals.callSites.test.ts +112 -0
- package/src/__tests__/principals.logging.test.ts +160 -0
- package/src/__tests__/principals.test.ts +305 -0
- package/src/__tests__/resolverBase.fls.test.ts +483 -0
- package/src/__tests__/resolverBase.recordChangesFls.test.ts +358 -0
- package/src/__tests__/resolverBase.refusalExtensions.test.ts +101 -0
- package/src/__tests__/resolverBase.refusalMessage.test.ts +88 -0
- package/src/__tests__/serverExtensionReservedRoots.test.ts +79 -11
- package/src/__tests__/visitorIdentity.resolve.test.ts +61 -0
- package/src/agentSessions/SessionJanitor.ts +2 -2
- package/src/auth/exampleNewUserSubClass.ts +9 -6
- package/src/auth/magicLink/MagicLinkService.ts +2 -8
- package/src/auth/newUsers.ts +7 -15
- package/src/auth/principals.ts +257 -0
- package/src/config.ts +44 -4
- package/src/entitySubclasses/MJEntityPermissionEntityServer.server.ts +65 -6
- package/src/generated/graphql-schemas/__mj.ts +18966 -16452
- package/src/generic/ResolverBase.ts +467 -9
- package/src/generic/RunViewResolver.ts +28 -2
- package/src/generic/refusalExtensions.ts +59 -0
- package/src/index.ts +154 -102
- package/src/realtimeWidget/WidgetSessionService.ts +2 -14
- package/src/realtimeWidget/visitorIdentity.ts +21 -6
- package/src/resolvers/EntityRecordNameResolver.ts +74 -8
- package/src/resolvers/FileCategoryResolver.ts +2 -3
- package/src/resolvers/IntegrationDiscoveryResolver.ts +2 -0
- package/src/resolvers/QuerySystemUserResolver.ts +1 -1
- package/src/resolvers/RealtimeClientSessionResolver.ts +128 -2
- package/src/resolvers/RemoteBrowserActionResolver.ts +47 -8
- package/src/resolvers/SyncRolesUsersResolver.ts +11 -2
- package/src/resolvers/UserViewResolver.ts +8 -4
- package/src/rest/EntityCRUDHandler.ts +3 -19
- package/src/rest/RESTEndpointHandler.ts +3 -17
- package/src/rest/RealtimeSdpBrokerHandler.ts +101 -0
- package/src/serverExtensionReservedRoots.ts +2 -3
- package/dist/resolvers/RingCentralTelephonyResolver.d.ts +0 -27
- package/dist/resolvers/RingCentralTelephonyResolver.d.ts.map +0 -1
- package/dist/resolvers/RingCentralTelephonyResolver.js +0 -87
- package/dist/resolvers/RingCentralTelephonyResolver.js.map +0 -1
- package/dist/resolvers/TeamsMeetingsResolver.d.ts +0 -28
- package/dist/resolvers/TeamsMeetingsResolver.d.ts.map +0 -1
- package/dist/resolvers/TeamsMeetingsResolver.js +0 -91
- package/dist/resolvers/TeamsMeetingsResolver.js.map +0 -1
- package/dist/resolvers/TelephonyResolver.d.ts +0 -26
- package/dist/resolvers/TelephonyResolver.d.ts.map +0 -1
- package/dist/resolvers/TelephonyResolver.js +0 -86
- package/dist/resolvers/TelephonyResolver.js.map +0 -1
- package/dist/resolvers/VonageTelephonyResolver.d.ts +0 -26
- package/dist/resolvers/VonageTelephonyResolver.d.ts.map +0 -1
- package/dist/resolvers/VonageTelephonyResolver.js +0 -86
- package/dist/resolvers/VonageTelephonyResolver.js.map +0 -1
- package/dist/telephony/RingCentralTelephonyService.d.ts +0 -115
- package/dist/telephony/RingCentralTelephonyService.d.ts.map +0 -1
- package/dist/telephony/RingCentralTelephonyService.js +0 -262
- package/dist/telephony/RingCentralTelephonyService.js.map +0 -1
- package/dist/telephony/TeamsMeetingsRouter.d.ts +0 -40
- package/dist/telephony/TeamsMeetingsRouter.d.ts.map +0 -1
- package/dist/telephony/TeamsMeetingsRouter.js +0 -96
- package/dist/telephony/TeamsMeetingsRouter.js.map +0 -1
- package/dist/telephony/TeamsMeetingsService.d.ts +0 -113
- package/dist/telephony/TeamsMeetingsService.d.ts.map +0 -1
- package/dist/telephony/TeamsMeetingsService.js +0 -196
- package/dist/telephony/TeamsMeetingsService.js.map +0 -1
- package/dist/telephony/TwilioTelephonyRouter.d.ts +0 -36
- package/dist/telephony/TwilioTelephonyRouter.d.ts.map +0 -1
- package/dist/telephony/TwilioTelephonyRouter.js +0 -143
- package/dist/telephony/TwilioTelephonyRouter.js.map +0 -1
- package/dist/telephony/TwilioTelephonyService.d.ts +0 -95
- package/dist/telephony/TwilioTelephonyService.d.ts.map +0 -1
- package/dist/telephony/TwilioTelephonyService.js +0 -193
- package/dist/telephony/TwilioTelephonyService.js.map +0 -1
- package/dist/telephony/VonageTelephonyRouter.d.ts +0 -41
- package/dist/telephony/VonageTelephonyRouter.d.ts.map +0 -1
- package/dist/telephony/VonageTelephonyRouter.js +0 -201
- package/dist/telephony/VonageTelephonyRouter.js.map +0 -1
- package/dist/telephony/VonageTelephonyService.d.ts +0 -90
- package/dist/telephony/VonageTelephonyService.d.ts.map +0 -1
- package/dist/telephony/VonageTelephonyService.js +0 -191
- package/dist/telephony/VonageTelephonyService.js.map +0 -1
- package/dist/telephony/calendar-scheduler.d.ts +0 -67
- package/dist/telephony/calendar-scheduler.d.ts.map +0 -1
- package/dist/telephony/calendar-scheduler.js +0 -133
- package/dist/telephony/calendar-scheduler.js.map +0 -1
- package/dist/telephony/index.d.ts +0 -29
- package/dist/telephony/index.d.ts.map +0 -1
- package/dist/telephony/index.js +0 -38
- package/dist/telephony/index.js.map +0 -1
- package/dist/telephony/media-upgrade-router.d.ts +0 -47
- package/dist/telephony/media-upgrade-router.d.ts.map +0 -1
- package/dist/telephony/media-upgrade-router.js +0 -72
- package/dist/telephony/media-upgrade-router.js.map +0 -1
- package/dist/telephony/ringcentral-runtime.d.ts +0 -14
- package/dist/telephony/ringcentral-runtime.d.ts.map +0 -1
- package/dist/telephony/ringcentral-runtime.js +0 -18
- package/dist/telephony/ringcentral-runtime.js.map +0 -1
- package/dist/telephony/teams-meetings-runtime.d.ts +0 -16
- package/dist/telephony/teams-meetings-runtime.d.ts.map +0 -1
- package/dist/telephony/teams-meetings-runtime.js +0 -20
- package/dist/telephony/teams-meetings-runtime.js.map +0 -1
- package/dist/telephony/teamsAcsMediaRegistry.d.ts +0 -69
- package/dist/telephony/teamsAcsMediaRegistry.d.ts.map +0 -1
- package/dist/telephony/teamsAcsMediaRegistry.js +0 -118
- package/dist/telephony/teamsAcsMediaRegistry.js.map +0 -1
- package/dist/telephony/telephony-runtime.d.ts +0 -14
- package/dist/telephony/telephony-runtime.d.ts.map +0 -1
- package/dist/telephony/telephony-runtime.js +0 -18
- package/dist/telephony/telephony-runtime.js.map +0 -1
- package/dist/telephony/twilioMediaRegistry.d.ts +0 -60
- package/dist/telephony/twilioMediaRegistry.d.ts.map +0 -1
- package/dist/telephony/twilioMediaRegistry.js +0 -106
- package/dist/telephony/twilioMediaRegistry.js.map +0 -1
- package/dist/telephony/vonage-runtime.d.ts +0 -14
- package/dist/telephony/vonage-runtime.d.ts.map +0 -1
- package/dist/telephony/vonage-runtime.js +0 -18
- package/dist/telephony/vonage-runtime.js.map +0 -1
- package/dist/telephony/vonageMediaRegistry.d.ts +0 -78
- package/dist/telephony/vonageMediaRegistry.d.ts.map +0 -1
- package/dist/telephony/vonageMediaRegistry.js +0 -158
- package/dist/telephony/vonageMediaRegistry.js.map +0 -1
- package/src/__tests__/media-upgrade-router.test.ts +0 -43
- package/src/__tests__/teams-meetings-service.test.ts +0 -65
- package/src/__tests__/teamsAcsMediaRegistry.test.ts +0 -82
- package/src/__tests__/twilio-telephony-service.test.ts +0 -23
- package/src/__tests__/twilioMediaRegistry.test.ts +0 -103
- package/src/__tests__/vonageMediaRegistry.test.ts +0 -180
- package/src/resolvers/RingCentralTelephonyResolver.ts +0 -64
- package/src/resolvers/TeamsMeetingsResolver.ts +0 -68
- package/src/resolvers/TelephonyResolver.ts +0 -63
- package/src/resolvers/VonageTelephonyResolver.ts +0 -63
- package/src/telephony/RingCentralTelephonyService.ts +0 -342
- package/src/telephony/TeamsMeetingsRouter.ts +0 -124
- package/src/telephony/TeamsMeetingsService.ts +0 -268
- package/src/telephony/TwilioTelephonyRouter.ts +0 -184
- package/src/telephony/TwilioTelephonyService.ts +0 -261
- package/src/telephony/VonageTelephonyRouter.ts +0 -239
- package/src/telephony/VonageTelephonyService.ts +0 -259
- package/src/telephony/calendar-scheduler.ts +0 -176
- package/src/telephony/index.ts +0 -43
- package/src/telephony/media-upgrade-router.ts +0 -79
- package/src/telephony/ringcentral-runtime.ts +0 -22
- package/src/telephony/teams-meetings-runtime.ts +0 -24
- package/src/telephony/teamsAcsMediaRegistry.ts +0 -152
- package/src/telephony/telephony-runtime.ts +0 -22
- package/src/telephony/twilioMediaRegistry.ts +0 -137
- package/src/telephony/vonage-runtime.ts +0 -22
- package/src/telephony/vonageMediaRegistry.ts +0 -200
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AggregateExpression, BaseEntity, CompositeKey, DatabaseProviderBase, EntityPermissionType, IMetadataProvider, RunViewResult, UserInfo } from '@memberjunction/core';
|
|
1
|
+
import { AggregateExpression, BaseEntity, CompositeKey, DatabaseProviderBase, EntityInfo, EntityPermissionType, IMetadataProvider, RecordChangeFieldSecurityProjector, RunViewResult, UserInfo } from '@memberjunction/core';
|
|
2
2
|
import { MJUserViewEntityExtended } from '@memberjunction/core-entities';
|
|
3
3
|
import { PubSubEngine } from 'type-graphql';
|
|
4
4
|
import { RunViewGenericParams, UserPayload } from '../types.js';
|
|
@@ -33,7 +33,7 @@ export declare class ResolverBase {
|
|
|
33
33
|
* @param contextUser - Optional user context for decryption (required for encrypted fields)
|
|
34
34
|
* @returns A new object in transport shape, or null when there is nothing to map
|
|
35
35
|
*/
|
|
36
|
-
protected MapFieldNamesToCodeNames(entityName: string, dataObject: any, contextUser?: UserInfo, provider?: IMetadataProvider): Promise<any>;
|
|
36
|
+
protected MapFieldNamesToCodeNames(entityName: string, dataObject: any, contextUser?: UserInfo, provider?: IMetadataProvider, deniedReadFields?: Set<string>, recordChangeProjector?: RecordChangeFieldSecurityProjector): Promise<any>;
|
|
37
37
|
/**
|
|
38
38
|
* Reverse-maps GraphQL-safe field names back to entity CodeNames in a mutation input object.
|
|
39
39
|
* For example, `_mj__integration_SyncStatus` is mapped back to `__mj_integration_SyncStatus`.
|
|
@@ -63,6 +63,17 @@ export declare class ResolverBase {
|
|
|
63
63
|
* returning the original) is what makes this safe on cache-served input.
|
|
64
64
|
*/
|
|
65
65
|
protected ArrayMapFieldNamesToCodeNames(entityName: string, dataObjectArray: any[], contextUser?: UserInfo, provider?: IMetadataProvider): Promise<any[]>;
|
|
66
|
+
/**
|
|
67
|
+
* The CodeNames this user may read on this entity, for the field-security transport key — or
|
|
68
|
+
* null when there is nothing to state (no denials, so every field is readable and the client
|
|
69
|
+
* needs no help distinguishing a withheld null from a genuine one).
|
|
70
|
+
*
|
|
71
|
+
* Carries entity field NAMES, not CodeNames and not the `_mj__` transport shape. The client
|
|
72
|
+
* consumes this after it has already reversed the transport mapping, and it matches names
|
|
73
|
+
* against `EntityFieldInfo.Name` — the same key the denied set itself is built from. Sending
|
|
74
|
+
* the one shape both sides already agree on avoids a second mapping that could drift.
|
|
75
|
+
*/
|
|
76
|
+
protected BuildReadableFieldsTransportValue(entityInfo: EntityInfo, deniedReadFields: Set<string> | null | undefined): string[] | null;
|
|
66
77
|
/**
|
|
67
78
|
* Loads a single external-data-source-backed entity record by primary key and returns it in
|
|
68
79
|
* GraphQL field-name (CodeName) shape, or null if not found.
|
|
@@ -141,6 +152,58 @@ export declare class ResolverBase {
|
|
|
141
152
|
* @throws AuthorizationError if API key lacks required scope
|
|
142
153
|
*/
|
|
143
154
|
protected CheckAPIKeyScopeAuthorization(scopePath: string, resource: string, userPayload: UserPayload): Promise<void>;
|
|
155
|
+
/**
|
|
156
|
+
* SECURITY — GraphQL-boundary screen for one client-supplied SQL clause fragment.
|
|
157
|
+
*
|
|
158
|
+
* `ValidateUserProvidedSQLClause` still blocks stacked statements, DML, comments, UNION
|
|
159
|
+
* and WAITFOR, and still permits SELECT (server-internal engines pass richer filters).
|
|
160
|
+
* A keyword ban on SELECT/EXISTS at this boundary (#4253) broke first-party clients that
|
|
161
|
+
* use `IN (SELECT … FROM <entity base view>)` — that is a legitimate ExtraFilter.
|
|
162
|
+
*
|
|
163
|
+
* This screen uses `@memberjunction/sql-parser` (same wrap as EDS `assertReadOnlyClause`):
|
|
164
|
+
* wrap the fragment as a single SELECT, fail closed if it does not parse as a read, then
|
|
165
|
+
* allow a FROM only when it is an entity **BaseView**. Base tables (`Meeting`, `__mj.User`)
|
|
166
|
+
* and catalogs are rejected. Server-internal RunView callers never hit this.
|
|
167
|
+
*
|
|
168
|
+
* RLS is applied by RunView as an outer WHERE around the entity being queried, not compiled
|
|
169
|
+
* into the view. Subqueries against another entity's BaseView therefore do not inherit that
|
|
170
|
+
* entity's RLS; they are still restricted to the view (not the table).
|
|
171
|
+
*/
|
|
172
|
+
protected assertClientClauseUsesEntityBaseViews(clause: string | undefined | null, label: string, provider?: IMetadataProvider): void;
|
|
173
|
+
/**
|
|
174
|
+
* Applies {@link assertClientClauseUsesEntityBaseViews} to every client-supplied clause
|
|
175
|
+
* a view request can carry that is actually a SQL fragment. GraphQL entry points
|
|
176
|
+
* (RunViewByName, RunViewByID, RunDynamicView, RunViews) funnel through
|
|
177
|
+
* RunViewGenericInternal / RunViewsGenericInternal.
|
|
178
|
+
*
|
|
179
|
+
* 🚨 `UserSearchString` is deliberately NOT screened here (#4392). It is not a clause — it is
|
|
180
|
+
* the free text a person typed into a search box, and it never reaches SQL as a fragment.
|
|
181
|
+
* `GenericDatabaseProvider.createViewUserSearchSQL` builds the predicate itself from
|
|
182
|
+
* `IncludeInUserSearchAPI` metadata and lands the text only as a literal, doubling single
|
|
183
|
+
* quotes and escaping LIKE metacharacters with an explicit `ESCAPE`. Running it through a
|
|
184
|
+
* screen that parses its argument as SQL and fails closed rejected every term that is not
|
|
185
|
+
* coincidentally valid SQL: `Marcus Chen` parses as nothing, `O'Leary` as an unterminated
|
|
186
|
+
* literal — so essentially every real name search returned 0 rows.
|
|
187
|
+
*
|
|
188
|
+
* The provider-level denylist does NOT back this up — it was removed from `UserSearchString`
|
|
189
|
+
* in the same change, for the same reason (it refused `Union Pacific`). What protects the value
|
|
190
|
+
* is that it is never SQL: it reaches the database only as a quoted, quote-doubled literal.
|
|
191
|
+
* The single place that is not true is a field carrying `UserSearchParamFormatAPI`, whose
|
|
192
|
+
* admin-authored format may splice the term in unquoted; `createViewUserSearchSQL` re-applies
|
|
193
|
+
* `ValidateUserProvidedSQLClause` for exactly those entities.
|
|
194
|
+
*/
|
|
195
|
+
protected screenClientViewClauses(clauses: {
|
|
196
|
+
extraFilter?: string | null;
|
|
197
|
+
orderBy?: string | null;
|
|
198
|
+
userSearchString?: string | null;
|
|
199
|
+
overrideExcludeFilter?: string | null;
|
|
200
|
+
}, provider?: IMetadataProvider): void;
|
|
201
|
+
/** Same write-node walk as EDS `sqlReadOnlyScreen.astContainsWriteNode`. */
|
|
202
|
+
private astContainsWriteNode;
|
|
203
|
+
private static readonly WRITE_NODE_TYPES;
|
|
204
|
+
private dialectForProvider;
|
|
205
|
+
private stripSqlIdent;
|
|
206
|
+
private entityBaseViewAllowList;
|
|
144
207
|
/**
|
|
145
208
|
* Optimized RunViewGenericInternal implementation with:
|
|
146
209
|
* - Field filtering at source (Fix #7)
|
|
@@ -182,6 +245,93 @@ export declare class ResolverBase {
|
|
|
182
245
|
protected BeforeCreate(provider: DatabaseProviderBase, input: any): Promise<boolean>;
|
|
183
246
|
protected AfterCreate(provider: DatabaseProviderBase, input: any): Promise<void>;
|
|
184
247
|
protected UpdateRecord(entityName: string, input: any, provider: DatabaseProviderBase, userPayload: UserPayload, pubSub: PubSubEngine): Promise<any>;
|
|
248
|
+
/**
|
|
249
|
+
* Whether `UpdateRecord` must hydrate the entity from the DATABASE rather than from the
|
|
250
|
+
* client's `OldValues___`.
|
|
251
|
+
*
|
|
252
|
+
* The `OldValues___` path exists as an optimization: when nothing needs the true prior state,
|
|
253
|
+
* the client already holds it and a round trip is wasted. Each condition below is a reason
|
|
254
|
+
* that assumption fails.
|
|
255
|
+
*
|
|
256
|
+
* `EnableFieldLevelSecurity` is the security-critical one, and it is NOT redundant with
|
|
257
|
+
* `hasDeniedReadFields`. That flag reports READ denials, and the canonical FLS configuration is
|
|
258
|
+
* Read Allow + Update Deny — which leaves it false. Such a caller would be hydrated from its own
|
|
259
|
+
* `OldValues___`, and a value it supplies there for an update-denied field arrives through
|
|
260
|
+
* `LoadFromData`, which the `EntityField` setter records as that field's INITIAL value. The
|
|
261
|
+
* field is therefore not dirty, `BaseEntity.CheckFieldLevelUpdatePermissions` only rejects
|
|
262
|
+
* `field.Dirty && denied`, and `GenerateSaveSQL` sends every `IsSPParameter` field regardless of
|
|
263
|
+
* dirtiness (it skips only `NotLoaded`). The fabricated value reached `spUpdate` having passed
|
|
264
|
+
* every check: pinning a value in `OldValues___` was a write to a field the caller may not write.
|
|
265
|
+
*
|
|
266
|
+
* Forcing the truth-load closes that rather than relocating it. The entity is hydrated by
|
|
267
|
+
* `InnerLoad` from the real row, and `TestAndSetClientOldValuesToDBValues` reads the client's
|
|
268
|
+
* OldValues only to detect concurrent-edit overlap before ending in `SetMany(clientNewValues)` —
|
|
269
|
+
* it never applies them to the entity. An update-denied field can then only become dirty by being
|
|
270
|
+
* named in the mutation input itself, which is precisely the case that check does catch.
|
|
271
|
+
*
|
|
272
|
+
* Ordered so the boolean flag is evaluated last: the extra load lands only on entities that have
|
|
273
|
+
* the feature switched on, which is almost none of them.
|
|
274
|
+
*/
|
|
275
|
+
protected MustLoadTruthFromDatabase(entityInfo: EntityInfo, input: {
|
|
276
|
+
OldValues___?: Array<{
|
|
277
|
+
Key: string;
|
|
278
|
+
Value: unknown;
|
|
279
|
+
}>;
|
|
280
|
+
}, hasDeniedReadFields: boolean, hasNarrowedAuditPayload: boolean): boolean;
|
|
281
|
+
/**
|
|
282
|
+
* Field-level security guard for the update path.
|
|
283
|
+
*
|
|
284
|
+
* Every denied-read field is stripped — new values AND OldValues. A field the user cannot
|
|
285
|
+
* read was absent from every payload that client ever received, so any value coming back for
|
|
286
|
+
* it is the transport's invention rather than user intent, and applying it would silently
|
|
287
|
+
* overwrite the real column. Stripping is what makes "load a record, edit an unrelated field,
|
|
288
|
+
* save" safe for a restricted user.
|
|
289
|
+
*
|
|
290
|
+
* There is no split by update permission: Read is required for Update, so a user denied read
|
|
291
|
+
* is denied update too and denied-read ∩ denied-update is just denied-read.
|
|
292
|
+
*
|
|
293
|
+
* Silent narrowing, not rejection — consistent with the output projection the client already
|
|
294
|
+
* experiences, and with the ambiguous-error rule (naming the field would confirm it exists
|
|
295
|
+
* and is restricted).
|
|
296
|
+
*
|
|
297
|
+
* Returns true when the user has a non-empty denied-read set on this entity. The caller
|
|
298
|
+
* must then hydrate the entity from the DATABASE (never from client OldValues), so denied
|
|
299
|
+
* fields hold true values that an omitted key leaves untouched.
|
|
300
|
+
*/
|
|
301
|
+
protected StripDeniedReadFieldsFromClientInput(entityInfo: EntityInfo, userInfo: UserInfo, input: {
|
|
302
|
+
OldValues___?: Array<{
|
|
303
|
+
Key: string;
|
|
304
|
+
Value: unknown;
|
|
305
|
+
}>;
|
|
306
|
+
} & Record<string, unknown>, clientNewValues: Record<string, unknown>): boolean;
|
|
307
|
+
/**
|
|
308
|
+
* Refuses a client-sent `MJ: Record Changes` payload column from a caller who carries field
|
|
309
|
+
* denials, and forces the update onto the load-truth-from-DB branch.
|
|
310
|
+
*
|
|
311
|
+
* This is the write half of the audit-trail projection, and without it that projection would
|
|
312
|
+
* itself destroy audit history. A restricted caller is served a NARROWED `ChangesJSON` /
|
|
313
|
+
* `FullRecordJSON` and no `ChangesDescription`. Those values hydrate a client-side entity as
|
|
314
|
+
* ordinary loaded values, and `GenerateSaveSQL` writes EVERY `IsSPParameter` field rather than
|
|
315
|
+
* only dirty ones — so a user who edits `Comments` on that record and saves would silently
|
|
316
|
+
* overwrite the stored payload with the narrowed one they were shown. The row would keep looking
|
|
317
|
+
* like a complete audit entry while the pruned fields were gone for everyone, permanently.
|
|
318
|
+
*
|
|
319
|
+
* The rule is the one field security already applies elsewhere: **a value a client could not
|
|
320
|
+
* have seen in full is not user intent, it is a transport artifact, and it is ignored.** Here
|
|
321
|
+
* that is widened from "fields the caller cannot read" to "the audit payload of a caller who
|
|
322
|
+
* carries any denial", because the column is readable — it is its CONTENTS that were narrowed,
|
|
323
|
+
* and which row's target entity did the narrowing is not knowable from the input alone.
|
|
324
|
+
*
|
|
325
|
+
* Returning true routes the caller through `InnerLoad`, so the stored values are restored from
|
|
326
|
+
* the database before the save. Legitimate payload writes are unaffected: they happen
|
|
327
|
+
* server-side (`SnapshotBuilder`, replay) and never through this resolver.
|
|
328
|
+
*/
|
|
329
|
+
protected StripRecordChangePayloadFromClientInput(entityInfo: EntityInfo, userInfo: UserInfo, input: {
|
|
330
|
+
OldValues___?: Array<{
|
|
331
|
+
Key: string;
|
|
332
|
+
Value: unknown;
|
|
333
|
+
}>;
|
|
334
|
+
} & Record<string, unknown>, clientNewValues: Record<string, unknown>, provider?: IMetadataProvider): boolean;
|
|
185
335
|
/**
|
|
186
336
|
* This routine compares the OldValues property in the input object to the values in the DB that we just loaded. If there are differences, we need to check to see if the client
|
|
187
337
|
* is trying to update any of those fields (e.g. overlap). If there is overlap, we throw an error. If there is no overlap, we can proceed with the update even if the DB Values
|
|
@@ -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,
|
|
1
|
+
{"version":3,"file":"ResolverBase.d.ts","sourceRoot":"","sources":["../../src/generic/ResolverBase.ts"],"names":[],"mappings":"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"}
|