@memberjunction/server 3.2.0 → 3.4.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 +106 -1
- package/dist/auth/APIKeyScopeAuth.d.ts +51 -0
- package/dist/auth/APIKeyScopeAuth.d.ts.map +1 -0
- package/dist/auth/APIKeyScopeAuth.js +163 -0
- package/dist/auth/APIKeyScopeAuth.js.map +1 -0
- package/dist/auth/BaseAuthProvider.d.ts +1 -0
- package/dist/auth/BaseAuthProvider.d.ts.map +1 -1
- package/dist/auth/BaseAuthProvider.js +2 -0
- package/dist/auth/BaseAuthProvider.js.map +1 -1
- package/dist/auth/IAuthProvider.d.ts +1 -0
- package/dist/auth/IAuthProvider.d.ts.map +1 -1
- package/dist/auth/index.d.ts +1 -0
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +1 -0
- package/dist/auth/index.js.map +1 -1
- package/dist/config.js +2 -2
- 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 +44 -7
- package/dist/context.js.map +1 -1
- package/dist/generated/generated.d.ts +681 -2
- package/dist/generated/generated.d.ts.map +1 -1
- package/dist/generated/generated.js +10627 -6409
- package/dist/generated/generated.js.map +1 -1
- package/dist/generic/ResolverBase.d.ts +3 -2
- package/dist/generic/ResolverBase.d.ts.map +1 -1
- package/dist/generic/ResolverBase.js +52 -4
- package/dist/generic/ResolverBase.js.map +1 -1
- package/dist/generic/RunViewResolver.d.ts +29 -1
- package/dist/generic/RunViewResolver.d.ts.map +1 -1
- package/dist/generic/RunViewResolver.js +143 -0
- package/dist/generic/RunViewResolver.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/resolvers/APIKeyResolver.d.ts +24 -0
- package/dist/resolvers/APIKeyResolver.d.ts.map +1 -0
- package/dist/resolvers/APIKeyResolver.js +194 -0
- package/dist/resolvers/APIKeyResolver.js.map +1 -0
- package/dist/resolvers/ActionResolver.d.ts +2 -1
- package/dist/resolvers/ActionResolver.d.ts.map +1 -1
- package/dist/resolvers/ActionResolver.js +4 -1
- package/dist/resolvers/ActionResolver.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 +7 -4
- package/dist/resolvers/DatasetResolver.js.map +1 -1
- package/dist/resolvers/EntityCommunicationsResolver.d.ts +2 -1
- package/dist/resolvers/EntityCommunicationsResolver.d.ts.map +1 -1
- package/dist/resolvers/EntityCommunicationsResolver.js +3 -1
- package/dist/resolvers/EntityCommunicationsResolver.js.map +1 -1
- package/dist/resolvers/GetDataContextDataResolver.d.ts +2 -1
- package/dist/resolvers/GetDataContextDataResolver.d.ts.map +1 -1
- package/dist/resolvers/GetDataContextDataResolver.js +10 -3
- package/dist/resolvers/GetDataContextDataResolver.js.map +1 -1
- package/dist/resolvers/MCPResolver.d.ts +37 -0
- package/dist/resolvers/MCPResolver.d.ts.map +1 -0
- package/dist/resolvers/MCPResolver.js +363 -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 +3 -1
- package/dist/resolvers/MergeRecordsResolver.js.map +1 -1
- package/dist/resolvers/QueryResolver.d.ts +2 -1
- package/dist/resolvers/QueryResolver.d.ts.map +1 -1
- package/dist/resolvers/QueryResolver.js +6 -1
- package/dist/resolvers/QueryResolver.js.map +1 -1
- package/dist/resolvers/ReportResolver.d.ts +2 -1
- package/dist/resolvers/ReportResolver.d.ts.map +1 -1
- package/dist/resolvers/ReportResolver.js +4 -1
- package/dist/resolvers/ReportResolver.js.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.js +3 -1
- package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
- package/dist/resolvers/RunAIPromptResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIPromptResolver.js +3 -0
- package/dist/resolvers/RunAIPromptResolver.js.map +1 -1
- package/dist/resolvers/RunTemplateResolver.d.ts.map +1 -1
- package/dist/resolvers/RunTemplateResolver.js +1 -0
- package/dist/resolvers/RunTemplateResolver.js.map +1 -1
- package/dist/resolvers/TaskResolver.d.ts.map +1 -1
- package/dist/resolvers/TaskResolver.js +1 -0
- package/dist/resolvers/TaskResolver.js.map +1 -1
- package/dist/resolvers/UserResolver.d.ts.map +1 -1
- package/dist/resolvers/UserResolver.js +35 -1
- package/dist/resolvers/UserResolver.js.map +1 -1
- package/dist/types.d.ts +4 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +47 -45
- package/src/auth/APIKeyScopeAuth.ts +366 -0
- package/src/auth/BaseAuthProvider.ts +3 -0
- package/src/auth/IAuthProvider.ts +5 -0
- package/src/auth/index.ts +1 -0
- package/src/config.ts +2 -2
- package/src/context.ts +91 -9
- package/src/generated/generated.ts +6327 -3668
- package/src/generic/ResolverBase.ts +127 -8
- package/src/generic/RunViewResolver.ts +132 -5
- package/src/index.ts +12 -2
- package/src/resolvers/APIKeyResolver.ts +241 -0
- 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/MCPResolver.ts +480 -0
- package/src/resolvers/MergeRecordsResolver.ts +5 -1
- package/src/resolvers/QueryResolver.ts +17 -3
- package/src/resolvers/ReportResolver.ts +8 -1
- package/src/resolvers/RunAIAgentResolver.ts +7 -1
- 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 +52 -4
- package/src/types.ts +7 -2
- package/dist/resolvers/AskSkipResolver.d.ts +0 -123
- package/dist/resolvers/AskSkipResolver.d.ts.map +0 -1
- package/dist/resolvers/AskSkipResolver.js +0 -1788
- package/dist/resolvers/AskSkipResolver.js.map +0 -1
- package/dist/scheduler/LearningCycleScheduler.d.ts +0 -4
- package/dist/scheduler/LearningCycleScheduler.d.ts.map +0 -1
- package/dist/scheduler/LearningCycleScheduler.js +0 -4
- package/dist/scheduler/LearningCycleScheduler.js.map +0 -1
- package/src/resolvers/AskSkipResolver.ts +0 -3446
- package/src/scheduler/LearningCycleScheduler.ts +0 -320
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import { Resolver, Mutation, Arg, Ctx } from "type-graphql";
|
|
2
|
+
import { Field, InputType, ObjectType } from "type-graphql";
|
|
3
|
+
import { LogError, Metadata } from "@memberjunction/core";
|
|
4
|
+
import { APIKeyScopeEntity } from "@memberjunction/core-entities";
|
|
5
|
+
import { GetAPIKeyEngine } from "@memberjunction/api-keys";
|
|
6
|
+
import { AppContext } from "../types.js";
|
|
7
|
+
import { ResolverBase } from "../generic/ResolverBase.js";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Input type for creating a new API key
|
|
11
|
+
*/
|
|
12
|
+
@InputType()
|
|
13
|
+
export class CreateAPIKeyInput {
|
|
14
|
+
/**
|
|
15
|
+
* Human-readable label for the API key
|
|
16
|
+
*/
|
|
17
|
+
@Field()
|
|
18
|
+
Label: string;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Optional description of what the key is used for
|
|
22
|
+
*/
|
|
23
|
+
@Field(() => String, { nullable: true })
|
|
24
|
+
Description?: string;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Optional expiration date for the key
|
|
28
|
+
*/
|
|
29
|
+
@Field(() => Date, { nullable: true })
|
|
30
|
+
ExpiresAt?: Date;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Optional array of scope IDs to assign to this key
|
|
34
|
+
*/
|
|
35
|
+
@Field(() => [String], { nullable: true })
|
|
36
|
+
ScopeIDs?: string[];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Result type for API key creation
|
|
41
|
+
* Returns the raw key ONCE - it cannot be recovered after this
|
|
42
|
+
*/
|
|
43
|
+
@ObjectType()
|
|
44
|
+
export class CreateAPIKeyResult {
|
|
45
|
+
/**
|
|
46
|
+
* Whether the key was created successfully
|
|
47
|
+
*/
|
|
48
|
+
@Field()
|
|
49
|
+
Success: boolean;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* The raw API key - show this to the user ONCE
|
|
53
|
+
* This cannot be recovered after the initial response
|
|
54
|
+
*/
|
|
55
|
+
@Field(() => String, { nullable: true })
|
|
56
|
+
RawKey?: string;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* The database ID of the created API key
|
|
60
|
+
*/
|
|
61
|
+
@Field(() => String, { nullable: true })
|
|
62
|
+
APIKeyID?: string;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Error message if creation failed
|
|
66
|
+
*/
|
|
67
|
+
@Field(() => String, { nullable: true })
|
|
68
|
+
Error?: string;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Result type for API key revocation
|
|
73
|
+
*/
|
|
74
|
+
@ObjectType()
|
|
75
|
+
export class RevokeAPIKeyResult {
|
|
76
|
+
/**
|
|
77
|
+
* Whether the key was revoked successfully
|
|
78
|
+
*/
|
|
79
|
+
@Field()
|
|
80
|
+
Success: boolean;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Error message if revocation failed
|
|
84
|
+
*/
|
|
85
|
+
@Field(() => String, { nullable: true })
|
|
86
|
+
Error?: string;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Resolver for API key operations
|
|
91
|
+
* Handles secure server-side API key generation
|
|
92
|
+
*/
|
|
93
|
+
@Resolver()
|
|
94
|
+
export class APIKeyResolver extends ResolverBase {
|
|
95
|
+
/**
|
|
96
|
+
* Creates a new API key with proper server-side cryptographic hashing.
|
|
97
|
+
*
|
|
98
|
+
* This mutation:
|
|
99
|
+
* 1. Generates a cryptographically secure API key using APIKeyEngine
|
|
100
|
+
* 2. Stores only the SHA-256 hash in the database (never the raw key)
|
|
101
|
+
* 3. Returns the raw key ONCE - it cannot be recovered after this call
|
|
102
|
+
* 4. Optionally assigns scope permissions to the key
|
|
103
|
+
*
|
|
104
|
+
* @param input The creation parameters
|
|
105
|
+
* @param ctx The GraphQL context with authenticated user
|
|
106
|
+
* @returns The raw key (show once!) and database ID
|
|
107
|
+
*/
|
|
108
|
+
@Mutation(() => CreateAPIKeyResult)
|
|
109
|
+
async CreateAPIKey(
|
|
110
|
+
@Arg("input") input: CreateAPIKeyInput,
|
|
111
|
+
@Ctx() ctx: AppContext
|
|
112
|
+
): Promise<CreateAPIKeyResult> {
|
|
113
|
+
// Check API key scope authorization for API key creation
|
|
114
|
+
await this.CheckAPIKeyScopeAuthorization('apikey:create', '*', ctx.userPayload);
|
|
115
|
+
|
|
116
|
+
try {
|
|
117
|
+
// Get the authenticated user
|
|
118
|
+
const user = ctx.userPayload.userRecord;
|
|
119
|
+
if (!user) {
|
|
120
|
+
return {
|
|
121
|
+
Success: false,
|
|
122
|
+
Error: "User is not authenticated"
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Use APIKeyEngine to create the API key with proper server-side crypto
|
|
127
|
+
const apiKeyEngine = GetAPIKeyEngine();
|
|
128
|
+
const result = await apiKeyEngine.CreateAPIKey(
|
|
129
|
+
{
|
|
130
|
+
UserId: user.ID,
|
|
131
|
+
Label: input.Label,
|
|
132
|
+
Description: input.Description,
|
|
133
|
+
ExpiresAt: input.ExpiresAt
|
|
134
|
+
},
|
|
135
|
+
user
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
if (!result.Success) {
|
|
139
|
+
return {
|
|
140
|
+
Success: false,
|
|
141
|
+
Error: result.Error || "Failed to create API key"
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Save scope associations if provided
|
|
146
|
+
if (input.ScopeIDs && input.ScopeIDs.length > 0 && result.APIKeyId) {
|
|
147
|
+
await this.saveScopeAssociations(result.APIKeyId, input.ScopeIDs, user);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return {
|
|
151
|
+
Success: true,
|
|
152
|
+
RawKey: result.RawKey,
|
|
153
|
+
APIKeyID: result.APIKeyId
|
|
154
|
+
};
|
|
155
|
+
} catch (e) {
|
|
156
|
+
const error = e as Error;
|
|
157
|
+
LogError(`Error in CreateAPIKey resolver: ${error.message}`);
|
|
158
|
+
return {
|
|
159
|
+
Success: false,
|
|
160
|
+
Error: `Error creating API key: ${error.message}`
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Revokes an API key, permanently disabling it.
|
|
167
|
+
*
|
|
168
|
+
* Once revoked, an API key cannot be reactivated. Users must create a new key.
|
|
169
|
+
* This uses APIKeyEngine.RevokeAPIKey() for consistency.
|
|
170
|
+
*
|
|
171
|
+
* @param apiKeyId The database ID of the API key to revoke
|
|
172
|
+
* @param ctx The GraphQL context with authenticated user
|
|
173
|
+
* @returns Success status
|
|
174
|
+
*/
|
|
175
|
+
@Mutation(() => RevokeAPIKeyResult)
|
|
176
|
+
async RevokeAPIKey(
|
|
177
|
+
@Arg("apiKeyId") apiKeyId: string,
|
|
178
|
+
@Ctx() ctx: AppContext
|
|
179
|
+
): Promise<RevokeAPIKeyResult> {
|
|
180
|
+
// Check API key scope authorization for API key revocation
|
|
181
|
+
await this.CheckAPIKeyScopeAuthorization('apikey:revoke', apiKeyId, ctx.userPayload);
|
|
182
|
+
|
|
183
|
+
try {
|
|
184
|
+
const user = ctx.userPayload.userRecord;
|
|
185
|
+
if (!user) {
|
|
186
|
+
return {
|
|
187
|
+
Success: false,
|
|
188
|
+
Error: "User is not authenticated"
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const apiKeyEngine = GetAPIKeyEngine();
|
|
193
|
+
const result = await apiKeyEngine.RevokeAPIKey(apiKeyId, user);
|
|
194
|
+
|
|
195
|
+
if (result) {
|
|
196
|
+
return { Success: true };
|
|
197
|
+
} else {
|
|
198
|
+
return {
|
|
199
|
+
Success: false,
|
|
200
|
+
Error: "Failed to revoke API key. It may not exist or you may not have permission."
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
} catch (e) {
|
|
204
|
+
const error = e as Error;
|
|
205
|
+
LogError(`Error in RevokeAPIKey resolver: ${error.message}`);
|
|
206
|
+
return {
|
|
207
|
+
Success: false,
|
|
208
|
+
Error: `Error revoking API key: ${error.message}`
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Saves scope associations for the newly created API key
|
|
215
|
+
* @param apiKeyId The ID of the created API key
|
|
216
|
+
* @param scopeIds Array of scope IDs to associate
|
|
217
|
+
* @param user The context user
|
|
218
|
+
*/
|
|
219
|
+
private async saveScopeAssociations(
|
|
220
|
+
apiKeyId: string,
|
|
221
|
+
scopeIds: string[],
|
|
222
|
+
user: any
|
|
223
|
+
): Promise<void> {
|
|
224
|
+
const md = new Metadata();
|
|
225
|
+
|
|
226
|
+
for (const scopeId of scopeIds) {
|
|
227
|
+
try {
|
|
228
|
+
const keyScope = await md.GetEntityObject<APIKeyScopeEntity>(
|
|
229
|
+
'MJ: API Key Scopes',
|
|
230
|
+
user
|
|
231
|
+
);
|
|
232
|
+
keyScope.APIKeyID = apiKeyId;
|
|
233
|
+
keyScope.ScopeID = scopeId;
|
|
234
|
+
await keyScope.Save();
|
|
235
|
+
} catch (error) {
|
|
236
|
+
LogError(`Error saving scope association for API key ${apiKeyId}, scope ${scopeId}: ${error}`);
|
|
237
|
+
// Continue with other scopes even if one fails
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
@@ -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();
|