@memberjunction/server 3.3.0 → 4.0.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 +59 -0
- package/dist/agents/skip-agent.d.ts +65 -0
- package/dist/agents/skip-agent.d.ts.map +1 -1
- package/dist/agents/skip-agent.js +63 -5
- package/dist/agents/skip-agent.js.map +1 -1
- package/dist/agents/skip-sdk.d.ts +163 -0
- package/dist/agents/skip-sdk.d.ts.map +1 -1
- package/dist/agents/skip-sdk.js +143 -12
- package/dist/agents/skip-sdk.js.map +1 -1
- package/dist/apolloServer/TransactionPlugin.d.ts +4 -0
- package/dist/apolloServer/TransactionPlugin.d.ts.map +1 -0
- package/dist/apolloServer/TransactionPlugin.js +46 -0
- package/dist/apolloServer/TransactionPlugin.js.map +1 -0
- package/dist/apolloServer/index.d.ts +0 -1
- package/dist/apolloServer/index.d.ts.map +1 -1
- package/dist/auth/APIKeyScopeAuth.d.ts +82 -0
- package/dist/auth/APIKeyScopeAuth.d.ts.map +1 -1
- package/dist/auth/APIKeyScopeAuth.js +78 -0
- package/dist/auth/APIKeyScopeAuth.js.map +1 -1
- package/dist/auth/AuthProviderFactory.d.ts +35 -0
- package/dist/auth/AuthProviderFactory.d.ts.map +1 -1
- package/dist/auth/AuthProviderFactory.js +51 -4
- package/dist/auth/AuthProviderFactory.js.map +1 -1
- package/dist/auth/BaseAuthProvider.d.ts +22 -0
- package/dist/auth/BaseAuthProvider.d.ts.map +1 -1
- package/dist/auth/BaseAuthProvider.js +25 -8
- package/dist/auth/BaseAuthProvider.js.map +1 -1
- package/dist/auth/IAuthProvider.d.ts +33 -0
- package/dist/auth/IAuthProvider.d.ts.map +1 -1
- package/dist/auth/__tests__/backward-compatibility.test.d.ts +2 -0
- package/dist/auth/__tests__/backward-compatibility.test.d.ts.map +1 -0
- package/dist/auth/__tests__/backward-compatibility.test.js +135 -0
- package/dist/auth/__tests__/backward-compatibility.test.js.map +1 -0
- package/dist/auth/exampleNewUserSubClass.d.ts +5 -1
- package/dist/auth/exampleNewUserSubClass.d.ts.map +1 -1
- package/dist/auth/exampleNewUserSubClass.js +21 -6
- package/dist/auth/exampleNewUserSubClass.js.map +1 -1
- package/dist/auth/index.d.ts +14 -0
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +35 -22
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/initializeProviders.d.ts +3 -0
- package/dist/auth/initializeProviders.d.ts.map +1 -1
- package/dist/auth/initializeProviders.js +6 -0
- package/dist/auth/initializeProviders.js.map +1 -1
- package/dist/auth/newUsers.js +11 -2
- package/dist/auth/newUsers.js.map +1 -1
- package/dist/auth/providers/Auth0Provider.d.ts +9 -0
- package/dist/auth/providers/Auth0Provider.d.ts.map +1 -1
- package/dist/auth/providers/Auth0Provider.js +10 -0
- package/dist/auth/providers/Auth0Provider.js.map +1 -1
- package/dist/auth/providers/CognitoProvider.d.ts +9 -0
- package/dist/auth/providers/CognitoProvider.d.ts.map +1 -1
- package/dist/auth/providers/CognitoProvider.js +10 -0
- package/dist/auth/providers/CognitoProvider.js.map +1 -1
- package/dist/auth/providers/GoogleProvider.d.ts +9 -0
- package/dist/auth/providers/GoogleProvider.d.ts.map +1 -1
- package/dist/auth/providers/GoogleProvider.js +11 -1
- package/dist/auth/providers/GoogleProvider.js.map +1 -1
- package/dist/auth/providers/MSALProvider.d.ts +9 -0
- package/dist/auth/providers/MSALProvider.d.ts.map +1 -1
- package/dist/auth/providers/MSALProvider.js +10 -0
- package/dist/auth/providers/MSALProvider.js.map +1 -1
- package/dist/auth/providers/OktaProvider.d.ts +9 -0
- package/dist/auth/providers/OktaProvider.d.ts.map +1 -1
- package/dist/auth/providers/OktaProvider.js +10 -0
- package/dist/auth/providers/OktaProvider.js.map +1 -1
- package/dist/config.d.ts +12 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +44 -10
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts +8 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +26 -4
- package/dist/context.js.map +1 -1
- package/dist/directives/Public.js +2 -0
- package/dist/directives/Public.js.map +1 -1
- package/dist/entitySubclasses/entityPermissions.server.d.ts +7 -2
- package/dist/entitySubclasses/entityPermissions.server.d.ts.map +1 -1
- package/dist/entitySubclasses/entityPermissions.server.js +26 -8
- package/dist/entitySubclasses/entityPermissions.server.js.map +1 -1
- package/dist/generated/generated.d.ts +954 -2
- package/dist/generated/generated.d.ts.map +1 -1
- package/dist/generated/generated.js +12183 -14532
- package/dist/generated/generated.js.map +1 -1
- package/dist/generic/DeleteOptionsInput.d.ts +3 -0
- package/dist/generic/DeleteOptionsInput.d.ts.map +1 -1
- package/dist/generic/DeleteOptionsInput.js +3 -2
- package/dist/generic/DeleteOptionsInput.js.map +1 -1
- package/dist/generic/KeyInputOutputTypes.js +0 -6
- package/dist/generic/KeyInputOutputTypes.js.map +1 -1
- package/dist/generic/KeyValuePairInput.d.ts +4 -0
- package/dist/generic/KeyValuePairInput.d.ts.map +1 -1
- package/dist/generic/KeyValuePairInput.js +4 -2
- package/dist/generic/KeyValuePairInput.js.map +1 -1
- package/dist/generic/PushStatusResolver.js +0 -3
- package/dist/generic/PushStatusResolver.js.map +1 -1
- package/dist/generic/ResolverBase.d.ts +59 -0
- package/dist/generic/ResolverBase.d.ts.map +1 -1
- package/dist/generic/ResolverBase.js +233 -18
- package/dist/generic/ResolverBase.js.map +1 -1
- package/dist/generic/RunViewResolver.d.ts +22 -0
- package/dist/generic/RunViewResolver.d.ts.map +1 -1
- package/dist/generic/RunViewResolver.js +42 -108
- package/dist/generic/RunViewResolver.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +84 -39
- package/dist/index.js.map +1 -1
- package/dist/orm.d.ts.map +1 -1
- package/dist/orm.js +2 -1
- package/dist/orm.js.map +1 -1
- package/dist/resolvers/APIKeyResolver.d.ts +76 -1
- package/dist/resolvers/APIKeyResolver.d.ts.map +1 -1
- package/dist/resolvers/APIKeyResolver.js +53 -11
- package/dist/resolvers/APIKeyResolver.js.map +1 -1
- package/dist/resolvers/ActionResolver.d.ts +191 -1
- package/dist/resolvers/ActionResolver.d.ts.map +1 -1
- package/dist/resolvers/ActionResolver.js +156 -22
- package/dist/resolvers/ActionResolver.js.map +1 -1
- package/dist/resolvers/ColorResolver.js +0 -5
- package/dist/resolvers/ColorResolver.js.map +1 -1
- package/dist/resolvers/ComponentRegistryResolver.d.ts +65 -0
- package/dist/resolvers/ComponentRegistryResolver.d.ts.map +1 -1
- package/dist/resolvers/ComponentRegistryResolver.js +118 -40
- package/dist/resolvers/ComponentRegistryResolver.js.map +1 -1
- package/dist/resolvers/CreateQueryResolver.d.ts +47 -0
- package/dist/resolvers/CreateQueryResolver.d.ts.map +1 -1
- package/dist/resolvers/CreateQueryResolver.js +92 -116
- package/dist/resolvers/CreateQueryResolver.js.map +1 -1
- package/dist/resolvers/DatasetResolver.d.ts +5 -4
- package/dist/resolvers/DatasetResolver.d.ts.map +1 -1
- package/dist/resolvers/DatasetResolver.js +9 -18
- package/dist/resolvers/DatasetResolver.js.map +1 -1
- package/dist/resolvers/EntityCommunicationsResolver.d.ts +42 -1
- package/dist/resolvers/EntityCommunicationsResolver.d.ts.map +1 -1
- package/dist/resolvers/EntityCommunicationsResolver.js +5 -37
- package/dist/resolvers/EntityCommunicationsResolver.js.map +1 -1
- package/dist/resolvers/EntityRecordNameResolver.js +0 -7
- package/dist/resolvers/EntityRecordNameResolver.js.map +1 -1
- package/dist/resolvers/FileCategoryResolver.js +13 -1
- package/dist/resolvers/FileCategoryResolver.js.map +1 -1
- package/dist/resolvers/FileResolver.d.ts +16 -0
- package/dist/resolvers/FileResolver.d.ts.map +1 -1
- package/dist/resolvers/FileResolver.js +59 -74
- package/dist/resolvers/FileResolver.js.map +1 -1
- package/dist/resolvers/GetDataContextDataResolver.d.ts +20 -2
- package/dist/resolvers/GetDataContextDataResolver.d.ts.map +1 -1
- package/dist/resolvers/GetDataContextDataResolver.js +27 -12
- package/dist/resolvers/GetDataContextDataResolver.js.map +1 -1
- package/dist/resolvers/GetDataResolver.d.ts +19 -0
- package/dist/resolvers/GetDataResolver.d.ts.map +1 -1
- package/dist/resolvers/GetDataResolver.js +35 -35
- package/dist/resolvers/GetDataResolver.js.map +1 -1
- package/dist/resolvers/InfoResolver.d.ts.map +1 -1
- package/dist/resolvers/InfoResolver.js +4 -7
- package/dist/resolvers/InfoResolver.js.map +1 -1
- package/dist/resolvers/MCPResolver.d.ts +361 -0
- package/dist/resolvers/MCPResolver.d.ts.map +1 -0
- package/dist/resolvers/MCPResolver.js +1270 -0
- package/dist/resolvers/MCPResolver.js.map +1 -0
- package/dist/resolvers/MergeRecordsResolver.d.ts +2 -1
- package/dist/resolvers/MergeRecordsResolver.d.ts.map +1 -1
- package/dist/resolvers/MergeRecordsResolver.js +6 -30
- package/dist/resolvers/MergeRecordsResolver.js.map +1 -1
- package/dist/resolvers/PotentialDuplicateRecordResolver.d.ts.map +1 -1
- package/dist/resolvers/PotentialDuplicateRecordResolver.js +0 -3
- package/dist/resolvers/PotentialDuplicateRecordResolver.js.map +1 -1
- package/dist/resolvers/QueryResolver.d.ts +22 -1
- package/dist/resolvers/QueryResolver.d.ts.map +1 -1
- package/dist/resolvers/QueryResolver.js +50 -37
- package/dist/resolvers/QueryResolver.js.map +1 -1
- package/dist/resolvers/ReportResolver.d.ts +5 -1
- package/dist/resolvers/ReportResolver.d.ts.map +1 -1
- package/dist/resolvers/ReportResolver.js +13 -11
- package/dist/resolvers/ReportResolver.js.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.d.ts +54 -0
- package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.js +118 -40
- package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
- package/dist/resolvers/RunAIPromptResolver.d.ts +42 -0
- package/dist/resolvers/RunAIPromptResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIPromptResolver.js +98 -22
- package/dist/resolvers/RunAIPromptResolver.js.map +1 -1
- package/dist/resolvers/RunTemplateResolver.d.ts.map +1 -1
- package/dist/resolvers/RunTemplateResolver.js +10 -6
- package/dist/resolvers/RunTemplateResolver.js.map +1 -1
- package/dist/resolvers/RunTestResolver.d.ts +12 -0
- package/dist/resolvers/RunTestResolver.d.ts.map +1 -1
- package/dist/resolvers/RunTestResolver.js +35 -21
- package/dist/resolvers/RunTestResolver.js.map +1 -1
- package/dist/resolvers/SqlLoggingConfigResolver.d.ts +312 -0
- package/dist/resolvers/SqlLoggingConfigResolver.d.ts.map +1 -1
- package/dist/resolvers/SqlLoggingConfigResolver.js +295 -45
- package/dist/resolvers/SqlLoggingConfigResolver.js.map +1 -1
- package/dist/resolvers/SyncDataResolver.d.ts +21 -0
- package/dist/resolvers/SyncDataResolver.d.ts.map +1 -1
- package/dist/resolvers/SyncDataResolver.js +36 -22
- package/dist/resolvers/SyncDataResolver.js.map +1 -1
- package/dist/resolvers/SyncRolesUsersResolver.d.ts +14 -0
- package/dist/resolvers/SyncRolesUsersResolver.d.ts.map +1 -1
- package/dist/resolvers/SyncRolesUsersResolver.js +54 -21
- package/dist/resolvers/SyncRolesUsersResolver.js.map +1 -1
- package/dist/resolvers/TaskResolver.d.ts +13 -0
- package/dist/resolvers/TaskResolver.d.ts.map +1 -1
- package/dist/resolvers/TaskResolver.js +23 -7
- package/dist/resolvers/TaskResolver.js.map +1 -1
- package/dist/resolvers/TelemetryResolver.d.ts +22 -0
- package/dist/resolvers/TelemetryResolver.d.ts.map +1 -1
- package/dist/resolvers/TelemetryResolver.js +45 -79
- package/dist/resolvers/TelemetryResolver.js.map +1 -1
- package/dist/resolvers/TransactionGroupResolver.js +11 -13
- package/dist/resolvers/TransactionGroupResolver.js.map +1 -1
- package/dist/resolvers/UserFavoriteResolver.js +3 -12
- package/dist/resolvers/UserFavoriteResolver.js.map +1 -1
- package/dist/resolvers/UserResolver.d.ts.map +1 -1
- package/dist/resolvers/UserResolver.js +14 -0
- package/dist/resolvers/UserResolver.js.map +1 -1
- package/dist/resolvers/UserViewResolver.js +4 -0
- package/dist/resolvers/UserViewResolver.js.map +1 -1
- package/dist/resolvers/VersionHistoryResolver.d.ts +39 -0
- package/dist/resolvers/VersionHistoryResolver.d.ts.map +1 -0
- package/dist/resolvers/VersionHistoryResolver.js +208 -0
- package/dist/resolvers/VersionHistoryResolver.js.map +1 -0
- package/dist/rest/EntityCRUDHandler.d.ts +19 -0
- package/dist/rest/EntityCRUDHandler.d.ts.map +1 -1
- package/dist/rest/EntityCRUDHandler.js +55 -0
- package/dist/rest/EntityCRUDHandler.js.map +1 -1
- package/dist/rest/OAuthCallbackHandler.d.ts +143 -0
- package/dist/rest/OAuthCallbackHandler.d.ts.map +1 -0
- package/dist/rest/OAuthCallbackHandler.js +634 -0
- package/dist/rest/OAuthCallbackHandler.js.map +1 -0
- package/dist/rest/RESTEndpointHandler.d.ts +120 -0
- package/dist/rest/RESTEndpointHandler.d.ts.map +1 -1
- package/dist/rest/RESTEndpointHandler.js +213 -24
- package/dist/rest/RESTEndpointHandler.js.map +1 -1
- package/dist/rest/ViewOperationsHandler.d.ts +19 -0
- package/dist/rest/ViewOperationsHandler.d.ts.map +1 -1
- package/dist/rest/ViewOperationsHandler.js +39 -0
- package/dist/rest/ViewOperationsHandler.js.map +1 -1
- package/dist/rest/index.d.ts +1 -0
- package/dist/rest/index.d.ts.map +1 -1
- package/dist/rest/index.js +1 -0
- package/dist/rest/index.js.map +1 -1
- package/dist/rest/setupRESTEndpoints.d.ts +35 -0
- package/dist/rest/setupRESTEndpoints.d.ts.map +1 -1
- package/dist/rest/setupRESTEndpoints.js +15 -1
- package/dist/rest/setupRESTEndpoints.js.map +1 -1
- package/dist/services/ScheduledJobsService.d.ts +31 -0
- package/dist/services/ScheduledJobsService.d.ts.map +1 -1
- package/dist/services/ScheduledJobsService.js +38 -4
- package/dist/services/ScheduledJobsService.js.map +1 -1
- package/dist/services/TaskOrchestrator.d.ts +73 -0
- package/dist/services/TaskOrchestrator.d.ts.map +1 -1
- package/dist/services/TaskOrchestrator.js +137 -15
- package/dist/services/TaskOrchestrator.js.map +1 -1
- package/dist/types.d.ts +14 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +0 -13
- package/dist/types.js.map +1 -1
- package/dist/util.d.ts +37 -1
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +55 -8
- package/dist/util.js.map +1 -1
- package/package.json +79 -77
- package/src/auth/BaseAuthProvider.ts +3 -0
- package/src/auth/IAuthProvider.ts +5 -0
- package/src/auth/exampleNewUserSubClass.ts +1 -5
- package/src/config.ts +2 -2
- package/src/entitySubclasses/entityPermissions.server.ts +1 -3
- package/src/generated/generated.ts +6245 -2558
- package/src/generic/ResolverBase.ts +89 -3
- package/src/index.ts +71 -64
- package/src/resolvers/APIKeyResolver.ts +8 -1
- package/src/resolvers/ActionResolver.ts +8 -1
- package/src/resolvers/DatasetResolver.ts +11 -4
- package/src/resolvers/EntityCommunicationsResolver.ts +5 -1
- package/src/resolvers/GetDataContextDataResolver.ts +14 -6
- package/src/resolvers/InfoResolver.ts +5 -1
- package/src/resolvers/MCPResolver.ts +1380 -0
- package/src/resolvers/MergeRecordsResolver.ts +5 -1
- package/src/resolvers/PotentialDuplicateRecordResolver.ts +0 -4
- package/src/resolvers/QueryResolver.ts +17 -3
- package/src/resolvers/ReportResolver.ts +8 -1
- package/src/resolvers/RunAIAgentResolver.ts +6 -0
- package/src/resolvers/RunAIPromptResolver.ts +10 -1
- package/src/resolvers/RunTemplateResolver.ts +4 -1
- package/src/resolvers/TaskResolver.ts +3 -0
- package/src/resolvers/UserResolver.ts +15 -3
- package/src/resolvers/VersionHistoryResolver.ts +177 -0
- package/src/rest/OAuthCallbackHandler.ts +766 -0
- package/src/rest/RESTEndpointHandler.ts +58 -35
- package/src/rest/index.ts +2 -1
- package/src/rest/setupRESTEndpoints.ts +13 -12
- package/src/resolvers/AskSkipResolver.ts +0 -3446
- package/src/scheduler/LearningCycleScheduler.ts +0 -320
|
@@ -19,8 +19,9 @@ import {
|
|
|
19
19
|
} from '@memberjunction/core';
|
|
20
20
|
import { AuditLogEntity, ErrorLogEntity, UserViewEntityExtended } from '@memberjunction/core-entities';
|
|
21
21
|
import { SQLServerDataProvider, UserCache } from '@memberjunction/sqlserver-dataprovider';
|
|
22
|
-
import { PubSubEngine } from 'type-graphql';
|
|
22
|
+
import { PubSubEngine, AuthorizationError } from 'type-graphql';
|
|
23
23
|
import { GraphQLError } from 'graphql';
|
|
24
|
+
import { GetAPIKeyEngine } from '@memberjunction/api-keys';
|
|
24
25
|
import sql from 'mssql';
|
|
25
26
|
import { httpTransport, CloudEvent, emitterFor } from 'cloudevents';
|
|
26
27
|
|
|
@@ -504,7 +505,7 @@ export class ResolverBase {
|
|
|
504
505
|
if (!userPayload) {
|
|
505
506
|
throw new Error(`userPayload is null`);
|
|
506
507
|
}
|
|
507
|
-
|
|
508
|
+
|
|
508
509
|
// first check permissions, the logged in user must have read permissions on the entity to run the view
|
|
509
510
|
if (entityInfo) {
|
|
510
511
|
const userInfo = UserCache.Users.find((u) => u.Email.toLowerCase().trim() === userPayload.email.toLowerCase().trim()); // get the user record from MD so we have ROLES attached, don't use the one from payload directly
|
|
@@ -516,12 +517,85 @@ export class ResolverBase {
|
|
|
516
517
|
if (!userPermissions.CanRead) {
|
|
517
518
|
throw new Error(`User ${userPayload.email} does not have read permissions on ${entityInfo.Name}`);
|
|
518
519
|
}
|
|
519
|
-
}
|
|
520
|
+
}
|
|
520
521
|
else {
|
|
521
522
|
throw new Error(`Entity not found in metadata`);
|
|
522
523
|
}
|
|
523
524
|
}
|
|
524
525
|
|
|
526
|
+
/**
|
|
527
|
+
* Checks API key scope authorization. Only performs check if request
|
|
528
|
+
* was authenticated via API key (apiKeyHash present in userPayload).
|
|
529
|
+
* For OAuth/JWT auth, this is a no-op.
|
|
530
|
+
*
|
|
531
|
+
* @param scopePath - The scope path (e.g., 'entity:read', 'agent:execute')
|
|
532
|
+
* @param resource - The resource name (e.g., entity name, agent name)
|
|
533
|
+
* @param userPayload - The user payload from context
|
|
534
|
+
* @throws AuthorizationError if API key lacks required scope
|
|
535
|
+
*/
|
|
536
|
+
protected async CheckAPIKeyScopeAuthorization(
|
|
537
|
+
scopePath: string,
|
|
538
|
+
resource: string,
|
|
539
|
+
userPayload: UserPayload
|
|
540
|
+
): Promise<void> {
|
|
541
|
+
// Skip scope check for OAuth/JWT auth (no API key)
|
|
542
|
+
if (!userPayload.apiKeyHash) {
|
|
543
|
+
return;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
// Get system user for authorization call
|
|
547
|
+
// NOTE: We use system user here because Authorize() needs to run internal
|
|
548
|
+
// database queries (loading scope rules, logging decisions). The system user
|
|
549
|
+
// ensures these queries work regardless of what permissions the API key's
|
|
550
|
+
// user has. The API key's associated user (in userPayload.userRecord) is
|
|
551
|
+
// used later when the actual operation executes - their permissions are
|
|
552
|
+
// the ultimate ceiling that scopes can only narrow, never expand.
|
|
553
|
+
const systemUser = UserCache.Instance.Users.find(u => u.Type === 'System');
|
|
554
|
+
if (!systemUser) {
|
|
555
|
+
throw new Error('System user not found');
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
const apiKeyEngine = GetAPIKeyEngine();
|
|
559
|
+
|
|
560
|
+
// Check for full_access scope first (god power - bypasses all other checks)
|
|
561
|
+
const fullAccessResult = await apiKeyEngine.Authorize(
|
|
562
|
+
userPayload.apiKeyHash,
|
|
563
|
+
'MJAPI',
|
|
564
|
+
'full_access',
|
|
565
|
+
'*',
|
|
566
|
+
systemUser,
|
|
567
|
+
{ endpoint: '/graphql', method: 'POST' }
|
|
568
|
+
);
|
|
569
|
+
|
|
570
|
+
if (fullAccessResult.Allowed) {
|
|
571
|
+
// full_access granted - skip specific scope check
|
|
572
|
+
return;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
// Check specific scope
|
|
576
|
+
const result = await apiKeyEngine.Authorize(
|
|
577
|
+
userPayload.apiKeyHash,
|
|
578
|
+
'MJAPI',
|
|
579
|
+
scopePath,
|
|
580
|
+
resource,
|
|
581
|
+
systemUser,
|
|
582
|
+
{
|
|
583
|
+
endpoint: '/graphql',
|
|
584
|
+
method: 'POST'
|
|
585
|
+
}
|
|
586
|
+
);
|
|
587
|
+
|
|
588
|
+
if (!result.Allowed) {
|
|
589
|
+
// Provide specific, actionable error message
|
|
590
|
+
throw new AuthorizationError(
|
|
591
|
+
`Access denied. This API key requires the '${scopePath}' scope ` +
|
|
592
|
+
`for resource '${resource}' to perform this operation. ` +
|
|
593
|
+
`Please update the API key's scopes or use an API key with appropriate permissions. ` +
|
|
594
|
+
`Denial reason: ${result.Reason}`
|
|
595
|
+
);
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
|
|
525
599
|
/**
|
|
526
600
|
* Optimized RunViewGenericInternal implementation with:
|
|
527
601
|
* - Field filtering at source (Fix #7)
|
|
@@ -550,6 +624,9 @@ export class ResolverBase {
|
|
|
550
624
|
try {
|
|
551
625
|
if (!viewInfo || !userPayload) return null;
|
|
552
626
|
|
|
627
|
+
// Check API key scope authorization for view operations
|
|
628
|
+
await this.CheckAPIKeyScopeAuthorization('view:run', viewInfo.Entity, userPayload);
|
|
629
|
+
|
|
553
630
|
const md = provider
|
|
554
631
|
const user = UserCache.Users.find((u) => u.Email.toLowerCase().trim() === userPayload?.email.toLowerCase().trim());
|
|
555
632
|
if (!user) throw new Error(`User ${userPayload?.email} not found in metadata`);
|
|
@@ -908,6 +985,9 @@ export class ResolverBase {
|
|
|
908
985
|
}
|
|
909
986
|
|
|
910
987
|
protected async CreateRecord(entityName: string, input: any, provider: DatabaseProviderBase, userPayload: UserPayload, pubSub: PubSubEngine) {
|
|
988
|
+
// Check API key scope authorization for entity create operations
|
|
989
|
+
await this.CheckAPIKeyScopeAuthorization('entity:create', entityName, userPayload);
|
|
990
|
+
|
|
911
991
|
if (await this.BeforeCreate(provider, input)) {
|
|
912
992
|
// fire event and proceed if it wasn't cancelled
|
|
913
993
|
const entityObject = await provider.GetEntityObject(entityName, this.GetUserFromPayload(userPayload));
|
|
@@ -940,6 +1020,9 @@ export class ResolverBase {
|
|
|
940
1020
|
protected async AfterCreate(provider: DatabaseProviderBase, input: any) {}
|
|
941
1021
|
|
|
942
1022
|
protected async UpdateRecord(entityName: string, input: any, provider: DatabaseProviderBase, userPayload: UserPayload, pubSub: PubSubEngine) {
|
|
1023
|
+
// Check API key scope authorization for entity update operations
|
|
1024
|
+
await this.CheckAPIKeyScopeAuthorization('entity:update', entityName, userPayload);
|
|
1025
|
+
|
|
943
1026
|
if (await this.BeforeUpdate(provider, input)) {
|
|
944
1027
|
// fire event and proceed if it wasn't cancelled
|
|
945
1028
|
const userInfo = this.GetUserFromPayload(userPayload);
|
|
@@ -1202,6 +1285,9 @@ export class ResolverBase {
|
|
|
1202
1285
|
userPayload: UserPayload,
|
|
1203
1286
|
pubSub: PubSubEngine
|
|
1204
1287
|
) {
|
|
1288
|
+
// Check API key scope authorization for entity delete operations
|
|
1289
|
+
await this.CheckAPIKeyScopeAuthorization('entity:delete', entityName, userPayload);
|
|
1290
|
+
|
|
1205
1291
|
if (await this.BeforeDelete(provider, key)) {
|
|
1206
1292
|
// fire event and proceed if it wasn't cancelled
|
|
1207
1293
|
const entityObject = await provider.GetEntityObject(entityName, this.GetUserFromPayload(userPayload));
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import dotenv from 'dotenv';
|
|
2
2
|
|
|
3
|
-
dotenv.config();
|
|
3
|
+
dotenv.config({ quiet: true });
|
|
4
4
|
|
|
5
5
|
import { expressMiddleware } from '@apollo/server/express4';
|
|
6
6
|
import { mergeSchemas } from '@graphql-tools/schema';
|
|
@@ -27,45 +27,10 @@ import { contextFunction, getUserPayload } from './context.js';
|
|
|
27
27
|
import { requireSystemUserDirective, publicDirective } from './directives/index.js';
|
|
28
28
|
import createMSSQLConfig from './orm.js';
|
|
29
29
|
import { setupRESTEndpoints } from './rest/setupRESTEndpoints.js';
|
|
30
|
-
|
|
31
|
-
import { LoadAllCoreActions } from '@memberjunction/core-actions';
|
|
32
|
-
LoadAllCoreActions(); // prevent tree shaking for this dynamic module
|
|
33
|
-
import { LoadApolloAccountsEnrichmentAction, LoadApolloContactsEnrichmentAction } from '@memberjunction/actions-apollo'
|
|
34
|
-
LoadApolloAccountsEnrichmentAction();
|
|
35
|
-
LoadApolloContactsEnrichmentAction();
|
|
36
|
-
|
|
37
|
-
import { LoadCoreEntitiesServerSubClasses } from '@memberjunction/core-entities-server';
|
|
38
|
-
LoadCoreEntitiesServerSubClasses(); // prevent tree shaking for this dynamic module
|
|
39
|
-
|
|
40
|
-
import { LoadAgentManagementActions } from '@memberjunction/ai-agent-manager-actions';
|
|
41
|
-
LoadAgentManagementActions();
|
|
42
|
-
|
|
43
|
-
// Load agent manager core classes (registers custom agent classes like AgentBuilderAgent, AgentArchitectAgent)
|
|
44
|
-
import { LoadAgentManagerCore } from '@memberjunction/ai-agent-manager';
|
|
45
|
-
LoadAgentManagerCore();
|
|
46
|
-
|
|
47
|
-
import { LoadSchedulingEngine } from '@memberjunction/scheduling-engine';
|
|
48
|
-
LoadSchedulingEngine(); // This also loads drivers
|
|
49
|
-
|
|
50
|
-
import { LoadAllSchedulingActions } from '@memberjunction/scheduling-actions';
|
|
51
|
-
LoadAllSchedulingActions(); // prevent tree shaking for scheduling actions
|
|
52
|
-
|
|
53
|
-
import { GetTypeformResponsesAction } from '@memberjunction/actions-bizapps-formbuilders';
|
|
54
|
-
const x = GetTypeformResponsesAction; // prevent tree shaking for this dynamic module
|
|
30
|
+
import { createOAuthCallbackHandler } from './rest/OAuthCallbackHandler.js';
|
|
55
31
|
|
|
56
32
|
import { resolve } from 'node:path';
|
|
57
33
|
import { DataSourceInfo, raiseEvent } from './types.js';
|
|
58
|
-
import { LoadAIEngine } from '@memberjunction/aiengine';
|
|
59
|
-
import { LoadAIProviders } from '@memberjunction/ai-provider-bundle';
|
|
60
|
-
// Load AI Engine and all providers to prevent tree shaking
|
|
61
|
-
LoadAIEngine();
|
|
62
|
-
LoadAIProviders();
|
|
63
|
-
|
|
64
|
-
// Load Communication Providers
|
|
65
|
-
import { LoadMSGraphProvider } from '@memberjunction/communication-ms-graph';
|
|
66
|
-
import { LoadProvider as LoadSendGridProvider } from '@memberjunction/communication-sendgrid';
|
|
67
|
-
LoadMSGraphProvider();
|
|
68
|
-
LoadSendGridProvider();
|
|
69
34
|
|
|
70
35
|
import { ExternalChangeDetectorEngine } from '@memberjunction/external-change-detection';
|
|
71
36
|
import { ScheduledJobsService } from './services/ScheduledJobsService.js';
|
|
@@ -81,7 +46,15 @@ export { configInfo, DEFAULT_SERVER_CONFIG } from './config.js';
|
|
|
81
46
|
export * from './directives/index.js';
|
|
82
47
|
export * from './entitySubclasses/entityPermissions.server.js';
|
|
83
48
|
export * from './types.js';
|
|
84
|
-
export {
|
|
49
|
+
export {
|
|
50
|
+
TokenExpiredError,
|
|
51
|
+
getSystemUser,
|
|
52
|
+
getSigningKeys,
|
|
53
|
+
extractUserInfoFromPayload,
|
|
54
|
+
verifyUserRecord,
|
|
55
|
+
AuthProviderFactory,
|
|
56
|
+
IAuthProvider,
|
|
57
|
+
} from './auth/index.js';
|
|
85
58
|
export * from './auth/APIKeyScopeAuth.js';
|
|
86
59
|
|
|
87
60
|
export * from './generic/PushStatusResolver.js';
|
|
@@ -98,7 +71,6 @@ export * from './generic/DeleteOptionsInput.js';
|
|
|
98
71
|
export * from './agents/skip-agent.js';
|
|
99
72
|
export * from './agents/skip-sdk.js';
|
|
100
73
|
|
|
101
|
-
export * from './resolvers/AskSkipResolver.js';
|
|
102
74
|
export * from './resolvers/ColorResolver.js';
|
|
103
75
|
export * from './resolvers/ComponentRegistryResolver.js';
|
|
104
76
|
export * from './resolvers/DatasetResolver.js';
|
|
@@ -115,6 +87,7 @@ export * from './resolvers/TransactionGroupResolver.js';
|
|
|
115
87
|
export * from './resolvers/CreateQueryResolver.js';
|
|
116
88
|
export * from './resolvers/TelemetryResolver.js';
|
|
117
89
|
export * from './resolvers/APIKeyResolver.js';
|
|
90
|
+
export * from './resolvers/MCPResolver.js';
|
|
118
91
|
export { GetReadOnlyDataSource, GetReadWriteDataSource, GetReadWriteProvider, GetReadOnlyProvider } from './util.js';
|
|
119
92
|
|
|
120
93
|
export * from './generated/generated.js';
|
|
@@ -292,20 +265,7 @@ export const serve = async (resolverPaths: Array<string>, app: Application = cre
|
|
|
292
265
|
level: 6
|
|
293
266
|
}));
|
|
294
267
|
|
|
295
|
-
|
|
296
|
-
graphqlRootPath,
|
|
297
|
-
cors<cors.CorsRequest>(),
|
|
298
|
-
BodyParser.json({ limit: '50mb' }),
|
|
299
|
-
expressMiddleware(apolloServer, {
|
|
300
|
-
context: contextFunction({
|
|
301
|
-
setupComplete$,
|
|
302
|
-
dataSource: extendConnectionPoolWithQuery(pool), // default read-write data source
|
|
303
|
-
dataSources // all data source
|
|
304
|
-
}),
|
|
305
|
-
})
|
|
306
|
-
);
|
|
307
|
-
|
|
308
|
-
// Setup REST API endpoints
|
|
268
|
+
// Setup REST API endpoints BEFORE GraphQL (since graphqlRootPath may be '/' which catches all routes)
|
|
309
269
|
const authMiddleware = async (req, res, next) => {
|
|
310
270
|
try {
|
|
311
271
|
const sessionIdRaw = req.headers['x-session-id'];
|
|
@@ -318,27 +278,58 @@ export const serve = async (resolverPaths: Array<string>, app: Application = cre
|
|
|
318
278
|
if (!userPayload) {
|
|
319
279
|
return res.status(401).json({ error: 'Invalid token' });
|
|
320
280
|
}
|
|
321
|
-
|
|
281
|
+
|
|
282
|
+
// Set both req.user (standard Express convention) and req['mjUser'] (MJ REST convention)
|
|
283
|
+
// Note: userPayload contains { userRecord: UserInfo, email, sessionId }
|
|
284
|
+
// The mjUser property expects the UserInfo directly (userRecord)
|
|
322
285
|
req.user = userPayload;
|
|
286
|
+
req['mjUser'] = userPayload.userRecord;
|
|
323
287
|
next();
|
|
324
288
|
} catch (error) {
|
|
325
289
|
console.error('Auth error:', error);
|
|
326
290
|
return res.status(401).json({ error: 'Authentication failed' });
|
|
327
291
|
}
|
|
328
292
|
};
|
|
329
|
-
|
|
330
|
-
//
|
|
331
|
-
const
|
|
332
|
-
|
|
293
|
+
|
|
294
|
+
// Build public URL for OAuth callbacks
|
|
295
|
+
const oauthPublicUrl = configInfo.publicUrl || `${configInfo.baseUrl}:${configInfo.graphqlPort}${configInfo.graphqlRootPath || ''}`;
|
|
296
|
+
console.log(`[OAuth] publicUrl: ${oauthPublicUrl}`);
|
|
297
|
+
|
|
298
|
+
// Set up OAuth callback routes at /oauth (independent of REST API)
|
|
299
|
+
// These must be registered BEFORE GraphQL middleware since graphqlRootPath may be '/'
|
|
300
|
+
if (oauthPublicUrl) {
|
|
301
|
+
const { callbackRouter, authenticatedRouter } = createOAuthCallbackHandler({
|
|
302
|
+
publicUrl: oauthPublicUrl,
|
|
303
|
+
// TODO: These should be configurable to point to the MJ Explorer UI
|
|
304
|
+
successRedirectUrl: `${oauthPublicUrl}/oauth/success`,
|
|
305
|
+
errorRedirectUrl: `${oauthPublicUrl}/oauth/error`
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
// Create CORS middleware for OAuth routes (needed for cross-origin requests from frontend)
|
|
309
|
+
const oauthCors = cors<cors.CorsRequest>();
|
|
310
|
+
|
|
311
|
+
// OAuth callback is unauthenticated (called by external auth server)
|
|
312
|
+
app.use('/oauth', oauthCors, callbackRouter);
|
|
313
|
+
console.log('[OAuth] Callback route registered at /oauth/callback');
|
|
314
|
+
|
|
315
|
+
// OAuth status, initiate, and exchange endpoints require authentication
|
|
316
|
+
// Must also have CORS for frontend requests and JSON body parsing
|
|
317
|
+
app.use('/oauth', oauthCors, BodyParser.json(), authMiddleware, authenticatedRouter);
|
|
318
|
+
console.log('[OAuth] Authenticated routes registered at /oauth/status, /oauth/initiate, and /oauth/exchange');
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// Get REST API configuration
|
|
322
|
+
const restApiConfig = {
|
|
323
|
+
enabled: configInfo.restApiOptions?.enabled ?? false,
|
|
333
324
|
includeEntities: configInfo.restApiOptions?.includeEntities,
|
|
334
|
-
excludeEntities: configInfo.restApiOptions?.excludeEntities
|
|
325
|
+
excludeEntities: configInfo.restApiOptions?.excludeEntities,
|
|
335
326
|
};
|
|
336
|
-
|
|
327
|
+
|
|
337
328
|
// Apply options from server options if provided (these override the config file)
|
|
338
329
|
if (options?.restApiOptions) {
|
|
339
330
|
Object.assign(restApiConfig, options.restApiOptions);
|
|
340
331
|
}
|
|
341
|
-
|
|
332
|
+
|
|
342
333
|
// Get REST API configuration from environment variables if present (env vars override everything)
|
|
343
334
|
if (process.env.MJ_REST_API_ENABLED !== undefined) {
|
|
344
335
|
restApiConfig.enabled = process.env.MJ_REST_API_ENABLED === 'true';
|
|
@@ -346,18 +337,34 @@ export const serve = async (resolverPaths: Array<string>, app: Application = cre
|
|
|
346
337
|
console.log('REST API is enabled via environment variable');
|
|
347
338
|
}
|
|
348
339
|
}
|
|
349
|
-
|
|
340
|
+
|
|
350
341
|
if (process.env.MJ_REST_API_INCLUDE_ENTITIES) {
|
|
351
342
|
restApiConfig.includeEntities = process.env.MJ_REST_API_INCLUDE_ENTITIES.split(',').map(e => e.trim());
|
|
352
343
|
}
|
|
353
|
-
|
|
344
|
+
|
|
354
345
|
if (process.env.MJ_REST_API_EXCLUDE_ENTITIES) {
|
|
355
346
|
restApiConfig.excludeEntities = process.env.MJ_REST_API_EXCLUDE_ENTITIES.split(',').map(e => e.trim());
|
|
356
347
|
}
|
|
357
|
-
|
|
348
|
+
|
|
358
349
|
// Set up REST endpoints with the configured options and auth middleware
|
|
359
350
|
setupRESTEndpoints(app, restApiConfig, authMiddleware);
|
|
360
351
|
|
|
352
|
+
// GraphQL middleware (after REST so /api/v1/* routes are handled first)
|
|
353
|
+
// Note: Type assertion needed due to @apollo/server bundling older @types/express types
|
|
354
|
+
// that are incompatible with Express 5.x types (missing 'param' property)
|
|
355
|
+
app.use(
|
|
356
|
+
graphqlRootPath,
|
|
357
|
+
cors<cors.CorsRequest>(),
|
|
358
|
+
BodyParser.json({ limit: '50mb' }),
|
|
359
|
+
expressMiddleware(apolloServer, {
|
|
360
|
+
context: contextFunction({
|
|
361
|
+
setupComplete$,
|
|
362
|
+
dataSource: extendConnectionPoolWithQuery(pool), // default read-write data source
|
|
363
|
+
dataSources // all data source
|
|
364
|
+
}),
|
|
365
|
+
}) as unknown as express.RequestHandler
|
|
366
|
+
);
|
|
367
|
+
|
|
361
368
|
// Initialize and start scheduled jobs service if enabled
|
|
362
369
|
let scheduledJobsService: ScheduledJobsService | null = null;
|
|
363
370
|
if (configInfo.scheduledJobs?.enabled) {
|
|
@@ -4,6 +4,7 @@ import { LogError, Metadata } from "@memberjunction/core";
|
|
|
4
4
|
import { APIKeyScopeEntity } from "@memberjunction/core-entities";
|
|
5
5
|
import { GetAPIKeyEngine } from "@memberjunction/api-keys";
|
|
6
6
|
import { AppContext } from "../types.js";
|
|
7
|
+
import { ResolverBase } from "../generic/ResolverBase.js";
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* Input type for creating a new API key
|
|
@@ -90,7 +91,7 @@ export class RevokeAPIKeyResult {
|
|
|
90
91
|
* Handles secure server-side API key generation
|
|
91
92
|
*/
|
|
92
93
|
@Resolver()
|
|
93
|
-
export class APIKeyResolver {
|
|
94
|
+
export class APIKeyResolver extends ResolverBase {
|
|
94
95
|
/**
|
|
95
96
|
* Creates a new API key with proper server-side cryptographic hashing.
|
|
96
97
|
*
|
|
@@ -109,6 +110,9 @@ export class APIKeyResolver {
|
|
|
109
110
|
@Arg("input") input: CreateAPIKeyInput,
|
|
110
111
|
@Ctx() ctx: AppContext
|
|
111
112
|
): Promise<CreateAPIKeyResult> {
|
|
113
|
+
// Check API key scope authorization for API key creation
|
|
114
|
+
await this.CheckAPIKeyScopeAuthorization('apikey:create', '*', ctx.userPayload);
|
|
115
|
+
|
|
112
116
|
try {
|
|
113
117
|
// Get the authenticated user
|
|
114
118
|
const user = ctx.userPayload.userRecord;
|
|
@@ -173,6 +177,9 @@ export class APIKeyResolver {
|
|
|
173
177
|
@Arg("apiKeyId") apiKeyId: string,
|
|
174
178
|
@Ctx() ctx: AppContext
|
|
175
179
|
): Promise<RevokeAPIKeyResult> {
|
|
180
|
+
// Check API key scope authorization for API key revocation
|
|
181
|
+
await this.CheckAPIKeyScopeAuthorization('apikey:revoke', apiKeyId, ctx.userPayload);
|
|
182
|
+
|
|
176
183
|
try {
|
|
177
184
|
const user = ctx.userPayload.userRecord;
|
|
178
185
|
if (!user) {
|
|
@@ -8,6 +8,7 @@ import { KeyValuePairInput } from "../generic/KeyValuePairInput.js";
|
|
|
8
8
|
import { AppContext, ProviderInfo } from "../types.js";
|
|
9
9
|
import { CopyScalarsAndArrays } from "@memberjunction/global";
|
|
10
10
|
import { GetReadOnlyProvider } from "../util.js";
|
|
11
|
+
import { ResolverBase } from "../generic/ResolverBase.js";
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* Input type for action parameters
|
|
@@ -171,7 +172,7 @@ export class ActionResultOutput {
|
|
|
171
172
|
* Handles running actions and entity actions through GraphQL
|
|
172
173
|
*/
|
|
173
174
|
@Resolver()
|
|
174
|
-
export class ActionResolver {
|
|
175
|
+
export class ActionResolver extends ResolverBase {
|
|
175
176
|
/**
|
|
176
177
|
* Mutation for running an action
|
|
177
178
|
* @param input The input parameters for running the action
|
|
@@ -184,6 +185,9 @@ export class ActionResolver {
|
|
|
184
185
|
@Ctx() ctx: AppContext
|
|
185
186
|
): Promise<ActionResultOutput> {
|
|
186
187
|
try {
|
|
188
|
+
// Check API key scope authorization for action execution
|
|
189
|
+
await this.CheckAPIKeyScopeAuthorization('action:execute', input.ActionID, ctx.userPayload);
|
|
190
|
+
|
|
187
191
|
// Get the user from context
|
|
188
192
|
const user = ctx.userPayload.userRecord;
|
|
189
193
|
if (!user) {
|
|
@@ -326,6 +330,9 @@ export class ActionResolver {
|
|
|
326
330
|
@Ctx() ctx: AppContext
|
|
327
331
|
): Promise<ActionResultOutput> {
|
|
328
332
|
try {
|
|
333
|
+
// Check API key scope authorization for entity action execution
|
|
334
|
+
await this.CheckAPIKeyScopeAuthorization('action:execute', input.EntityActionID, ctx.userPayload);
|
|
335
|
+
|
|
329
336
|
const user = ctx.userPayload.userRecord;
|
|
330
337
|
if (!user) {
|
|
331
338
|
throw new Error("User is not authenticated");
|
|
@@ -2,6 +2,7 @@ import { Arg, Ctx, Field, InputType, Int, ObjectType, Query, Resolver } from 'ty
|
|
|
2
2
|
import { AppContext } from '../types.js';
|
|
3
3
|
import { LogError, Metadata } from '@memberjunction/core';
|
|
4
4
|
import { GetReadOnlyProvider } from '../util.js';
|
|
5
|
+
import { ResolverBase } from '../generic/ResolverBase.js';
|
|
5
6
|
|
|
6
7
|
@ObjectType()
|
|
7
8
|
export class DatasetResultType {
|
|
@@ -35,13 +36,16 @@ export class DatasetItemFilterTypeGQL {
|
|
|
35
36
|
|
|
36
37
|
|
|
37
38
|
@Resolver(DatasetResultType)
|
|
38
|
-
export class DatasetResolverExtended {
|
|
39
|
+
export class DatasetResolverExtended extends ResolverBase {
|
|
39
40
|
@Query(() => DatasetResultType)
|
|
40
41
|
async GetDatasetByName(
|
|
41
42
|
@Arg('DatasetName', () => String) DatasetName: string,
|
|
42
|
-
@Ctx() {providers}: AppContext,
|
|
43
|
+
@Ctx() { providers, userPayload }: AppContext,
|
|
43
44
|
@Arg('ItemFilters', () => [DatasetItemFilterTypeGQL], { nullable: 'itemsAndList' }) ItemFilters?: DatasetItemFilterTypeGQL[]
|
|
44
45
|
) {
|
|
46
|
+
// Check API key scope authorization for dataset read
|
|
47
|
+
await this.CheckAPIKeyScopeAuthorization('dataset:read', DatasetName, userPayload);
|
|
48
|
+
|
|
45
49
|
try {
|
|
46
50
|
const md = GetReadOnlyProvider(providers, {allowFallbackToReadWrite: true});
|
|
47
51
|
const result = await md.GetDatasetByName(DatasetName, ItemFilters);
|
|
@@ -86,13 +90,16 @@ export class DatasetStatusResultType {
|
|
|
86
90
|
}
|
|
87
91
|
|
|
88
92
|
@Resolver(DatasetStatusResultType)
|
|
89
|
-
export class DatasetStatusResolver {
|
|
93
|
+
export class DatasetStatusResolver extends ResolverBase {
|
|
90
94
|
@Query(() => DatasetStatusResultType)
|
|
91
95
|
async GetDatasetStatusByName(
|
|
92
96
|
@Arg('DatasetName', () => String) DatasetName: string,
|
|
93
|
-
@Ctx() {providers}: AppContext,
|
|
97
|
+
@Ctx() { providers, userPayload }: AppContext,
|
|
94
98
|
@Arg('ItemFilters', () => [DatasetItemFilterTypeGQL], { nullable: 'itemsAndList' }) ItemFilters?: DatasetItemFilterTypeGQL[]
|
|
95
99
|
) {
|
|
100
|
+
// Check API key scope authorization for dataset read
|
|
101
|
+
await this.CheckAPIKeyScopeAuthorization('dataset:read', DatasetName, userPayload);
|
|
102
|
+
|
|
96
103
|
try {
|
|
97
104
|
const md = GetReadOnlyProvider(providers, {allowFallbackToReadWrite: true});
|
|
98
105
|
const result = await md.GetDatasetStatusByName(DatasetName, ItemFilters);
|
|
@@ -8,6 +8,7 @@ import { GraphQLJSONObject } from 'graphql-type-json';
|
|
|
8
8
|
import { TemplateEngineServer } from '@memberjunction/templates';
|
|
9
9
|
import { EntityCommunicationParams } from '@memberjunction/entity-communications-base';
|
|
10
10
|
import { z } from 'zod';
|
|
11
|
+
import { ResolverBase } from '../generic/ResolverBase.js';
|
|
11
12
|
|
|
12
13
|
@InputType()
|
|
13
14
|
export class CommunicationProviderMessageType {
|
|
@@ -166,7 +167,7 @@ export class RunEntityCommunicationResultType {
|
|
|
166
167
|
}
|
|
167
168
|
|
|
168
169
|
@Resolver(RunEntityCommunicationResultType)
|
|
169
|
-
export class ReportResolver {
|
|
170
|
+
export class ReportResolver extends ResolverBase {
|
|
170
171
|
@Query(() => RunEntityCommunicationResultType)
|
|
171
172
|
async RunEntityCommunicationByViewID(
|
|
172
173
|
@Arg('entityID', () => String) entityID: string,
|
|
@@ -178,6 +179,9 @@ export class ReportResolver {
|
|
|
178
179
|
@Arg('includeProcessedMessages', () => Boolean) includeProcessedMessages: boolean,
|
|
179
180
|
@Ctx() { userPayload }: AppContext
|
|
180
181
|
): Promise<RunEntityCommunicationResultType> {
|
|
182
|
+
// Check API key scope authorization for communication send
|
|
183
|
+
await this.CheckAPIKeyScopeAuthorization('communication:send', entityID, userPayload);
|
|
184
|
+
|
|
181
185
|
try {
|
|
182
186
|
await EntityCommunicationsEngine.Instance.Config(false, userPayload.userRecord);
|
|
183
187
|
const newMessage = new Message(message as unknown as Message);
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { Arg, Ctx, Field, ObjectType, Query } from "type-graphql";
|
|
1
|
+
import { Arg, Ctx, Field, ObjectType, Query, Resolver } from "type-graphql";
|
|
2
2
|
import { AppContext } from "../types.js";
|
|
3
3
|
import { DataContext } from "@memberjunction/data-context";
|
|
4
4
|
import { GetReadOnlyDataSource, GetReadOnlyProvider } from "../util.js";
|
|
5
5
|
import { Metadata } from "@memberjunction/core";
|
|
6
6
|
import { DataContextItemEntity } from "@memberjunction/core-entities";
|
|
7
|
+
import { ResolverBase } from "../generic/ResolverBase.js";
|
|
7
8
|
|
|
8
9
|
@ObjectType()
|
|
9
10
|
export class GetDataContextItemDataOutputType {
|
|
@@ -39,16 +40,20 @@ export class GetDataContextDataOutputType {
|
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
|
|
42
|
-
|
|
43
|
+
@Resolver()
|
|
44
|
+
export class GetDataContextDataResolver extends ResolverBase {
|
|
43
45
|
/**
|
|
44
|
-
* Returns data for a given data context item.
|
|
45
|
-
* @param DataContextItemID
|
|
46
|
+
* Returns data for a given data context item.
|
|
47
|
+
* @param DataContextItemID
|
|
46
48
|
*/
|
|
47
49
|
@Query(() => GetDataContextItemDataOutputType)
|
|
48
50
|
async GetDataContextItemData(
|
|
49
51
|
@Arg('DataContextItemID', () => String) DataContextItemID: string,
|
|
50
52
|
@Ctx() appCtx: AppContext
|
|
51
53
|
) {
|
|
54
|
+
// Check API key scope authorization for data context read
|
|
55
|
+
await this.CheckAPIKeyScopeAuthorization('datacontext:read', DataContextItemID, appCtx.userPayload);
|
|
56
|
+
|
|
52
57
|
try {
|
|
53
58
|
const ds = GetReadOnlyDataSource(appCtx.dataSources, {
|
|
54
59
|
allowFallbackToReadWrite: true,
|
|
@@ -92,14 +97,17 @@ export class GetDataContextDataResolver {
|
|
|
92
97
|
}
|
|
93
98
|
|
|
94
99
|
/**
|
|
95
|
-
* Returns data for a given data context.
|
|
96
|
-
* @param DataContextID
|
|
100
|
+
* Returns data for a given data context.
|
|
101
|
+
* @param DataContextID
|
|
97
102
|
*/
|
|
98
103
|
@Query(() => GetDataContextDataOutputType)
|
|
99
104
|
async GetDataContextData(
|
|
100
105
|
@Arg('DataContextID', () => String) DataContextID: string,
|
|
101
106
|
@Ctx() appCtx: AppContext
|
|
102
107
|
) {
|
|
108
|
+
// Check API key scope authorization for data context read
|
|
109
|
+
await this.CheckAPIKeyScopeAuthorization('datacontext:read', DataContextID, appCtx.userPayload);
|
|
110
|
+
|
|
103
111
|
try {
|
|
104
112
|
// our job here is to load the entire data context, so we do that with the Data Context object
|
|
105
113
|
const dc = new DataContext();
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { Field, ObjectType, Int, Query, Resolver, Ctx, Info as RequestInfo } from 'type-graphql';
|
|
2
2
|
import { Public, RequireSystemUser } from '../directives/index.js';
|
|
3
|
-
import
|
|
3
|
+
import { createRequire } from 'node:module';
|
|
4
4
|
import { AppContext } from '../types.js';
|
|
5
5
|
import os from 'node:os';
|
|
6
6
|
|
|
7
|
+
// Use createRequire to import JSON (compatible with module: es2022)
|
|
8
|
+
const require = createRequire(import.meta.url);
|
|
9
|
+
const packageJson = require('../../package.json') as { version: string };
|
|
10
|
+
|
|
7
11
|
@ObjectType()
|
|
8
12
|
export class Info {
|
|
9
13
|
@Public()
|