@memberjunction/server 2.75.0 → 2.77.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 +61 -2
- package/dist/apolloServer/index.d.ts.map +1 -1
- package/dist/apolloServer/index.js +1 -3
- package/dist/apolloServer/index.js.map +1 -1
- package/dist/auth/exampleNewUserSubClass.d.ts +1 -1
- package/dist/auth/exampleNewUserSubClass.d.ts.map +1 -1
- package/dist/auth/exampleNewUserSubClass.js +1 -1
- package/dist/auth/exampleNewUserSubClass.js.map +1 -1
- package/dist/auth/newUsers.js.map +1 -1
- package/dist/context.d.ts +5 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +34 -3
- package/dist/context.js.map +1 -1
- package/dist/entitySubclasses/entityPermissions.server.d.ts +2 -2
- package/dist/entitySubclasses/entityPermissions.server.d.ts.map +1 -1
- package/dist/entitySubclasses/entityPermissions.server.js +2 -2
- package/dist/entitySubclasses/entityPermissions.server.js.map +1 -1
- package/dist/generated/generated.d.ts +1787 -1628
- package/dist/generated/generated.d.ts.map +1 -1
- package/dist/generated/generated.js +5871 -4367
- package/dist/generated/generated.js.map +1 -1
- package/dist/generic/ResolverBase.d.ts +20 -21
- package/dist/generic/ResolverBase.d.ts.map +1 -1
- package/dist/generic/ResolverBase.js +75 -59
- package/dist/generic/ResolverBase.js.map +1 -1
- package/dist/generic/RunViewResolver.d.ts +8 -8
- package/dist/generic/RunViewResolver.d.ts.map +1 -1
- package/dist/generic/RunViewResolver.js +50 -48
- package/dist/generic/RunViewResolver.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/resolvers/AskSkipResolver.d.ts +6 -6
- package/dist/resolvers/AskSkipResolver.d.ts.map +1 -1
- package/dist/resolvers/AskSkipResolver.js +33 -21
- package/dist/resolvers/AskSkipResolver.js.map +1 -1
- package/dist/resolvers/CreateQueryResolver.d.ts +12 -3
- package/dist/resolvers/CreateQueryResolver.d.ts.map +1 -1
- package/dist/resolvers/CreateQueryResolver.js +121 -65
- package/dist/resolvers/CreateQueryResolver.js.map +1 -1
- package/dist/resolvers/EntityResolver.d.ts +1 -2
- package/dist/resolvers/EntityResolver.d.ts.map +1 -1
- package/dist/resolvers/EntityResolver.js +17 -9
- package/dist/resolvers/EntityResolver.js.map +1 -1
- package/dist/resolvers/FileCategoryResolver.d.ts +1 -1
- package/dist/resolvers/FileCategoryResolver.d.ts.map +1 -1
- package/dist/resolvers/FileCategoryResolver.js +9 -9
- package/dist/resolvers/FileCategoryResolver.js.map +1 -1
- package/dist/resolvers/FileResolver.d.ts.map +1 -1
- package/dist/resolvers/FileResolver.js +3 -1
- package/dist/resolvers/FileResolver.js.map +1 -1
- package/dist/resolvers/GetDataResolver.d.ts.map +1 -1
- package/dist/resolvers/GetDataResolver.js +3 -0
- package/dist/resolvers/GetDataResolver.js.map +1 -1
- package/dist/resolvers/MergeRecordsResolver.d.ts.map +1 -1
- package/dist/resolvers/MergeRecordsResolver.js +2 -1
- package/dist/resolvers/MergeRecordsResolver.js.map +1 -1
- package/dist/resolvers/QueryResolver.d.ts +4 -4
- package/dist/resolvers/QueryResolver.js +18 -18
- package/dist/resolvers/ReportResolver.js.map +1 -1
- package/dist/resolvers/SyncDataResolver.d.ts +8 -8
- package/dist/resolvers/SyncDataResolver.d.ts.map +1 -1
- package/dist/resolvers/SyncDataResolver.js +19 -19
- package/dist/resolvers/SyncDataResolver.js.map +1 -1
- package/dist/resolvers/SyncRolesUsersResolver.d.ts +10 -10
- package/dist/resolvers/SyncRolesUsersResolver.d.ts.map +1 -1
- package/dist/resolvers/SyncRolesUsersResolver.js +19 -19
- package/dist/resolvers/SyncRolesUsersResolver.js.map +1 -1
- package/dist/resolvers/TransactionGroupResolver.d.ts.map +1 -1
- package/dist/resolvers/TransactionGroupResolver.js.map +1 -1
- package/dist/resolvers/UserFavoriteResolver.d.ts +2 -2
- package/dist/resolvers/UserFavoriteResolver.d.ts.map +1 -1
- package/dist/resolvers/UserFavoriteResolver.js +7 -4
- package/dist/resolvers/UserFavoriteResolver.js.map +1 -1
- package/dist/resolvers/UserResolver.d.ts +3 -3
- package/dist/resolvers/UserResolver.d.ts.map +1 -1
- package/dist/resolvers/UserResolver.js +10 -6
- package/dist/resolvers/UserResolver.js.map +1 -1
- package/dist/resolvers/UserViewResolver.d.ts +2 -2
- package/dist/resolvers/UserViewResolver.d.ts.map +1 -1
- package/dist/resolvers/UserViewResolver.js +11 -6
- package/dist/resolvers/UserViewResolver.js.map +1 -1
- package/dist/scheduler/LearningCycleScheduler.d.ts.map +1 -1
- package/dist/scheduler/LearningCycleScheduler.js +7 -1
- package/dist/scheduler/LearningCycleScheduler.js.map +1 -1
- package/dist/types.d.ts +7 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +4 -0
- package/dist/types.js.map +1 -1
- package/dist/util.d.ts +8 -1
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +28 -0
- package/dist/util.js.map +1 -1
- package/package.json +34 -34
- package/src/apolloServer/index.ts +3 -3
- package/src/auth/exampleNewUserSubClass.ts +3 -2
- package/src/auth/newUsers.ts +1 -1
- package/src/context.ts +49 -9
- package/src/entitySubclasses/entityPermissions.server.ts +3 -3
- package/src/generated/generated.ts +5506 -4368
- package/src/generic/ResolverBase.ts +103 -86
- package/src/generic/RunViewResolver.ts +55 -54
- package/src/index.ts +1 -1
- package/src/resolvers/AskSkipResolver.ts +44 -23
- package/src/resolvers/CreateQueryResolver.ts +104 -62
- package/src/resolvers/EntityResolver.ts +18 -9
- package/src/resolvers/FileCategoryResolver.ts +12 -9
- package/src/resolvers/FileResolver.ts +4 -2
- package/src/resolvers/GetDataResolver.ts +3 -0
- package/src/resolvers/MergeRecordsResolver.ts +2 -1
- package/src/resolvers/QueryResolver.ts +14 -14
- package/src/resolvers/ReportResolver.ts +1 -1
- package/src/resolvers/SyncDataResolver.ts +21 -21
- package/src/resolvers/SyncRolesUsersResolver.ts +24 -21
- package/src/resolvers/TransactionGroupResolver.ts +1 -1
- package/src/resolvers/UserFavoriteResolver.ts +7 -5
- package/src/resolvers/UserResolver.ts +10 -6
- package/src/resolvers/UserViewResolver.ts +13 -7
- package/src/scheduler/LearningCycleScheduler.ts +10 -4
- package/src/types.ts +14 -4
- package/src/util.ts +45 -2
- package/dist/apolloServer/TransactionPlugin.d.ts +0 -4
- package/dist/apolloServer/TransactionPlugin.d.ts.map +0 -1
- package/dist/apolloServer/TransactionPlugin.js +0 -46
- package/dist/apolloServer/TransactionPlugin.js.map +0 -1
- package/src/apolloServer/TransactionPlugin.ts +0 -53
|
@@ -38,7 +38,7 @@ export class RunQueryResultType {
|
|
|
38
38
|
|
|
39
39
|
@Resolver()
|
|
40
40
|
export class RunQueryResolver {
|
|
41
|
-
private async findQuery(QueryID: string, QueryName?: string, CategoryID?: string,
|
|
41
|
+
private async findQuery(QueryID: string, QueryName?: string, CategoryID?: string, CategoryPath?: string, refreshMetadataIfNotFound: boolean = false): Promise<QueryInfo | null> {
|
|
42
42
|
const md = new Metadata();
|
|
43
43
|
|
|
44
44
|
// Filter queries based on provided criteria
|
|
@@ -50,8 +50,8 @@ export class RunQueryResolver {
|
|
|
50
50
|
if (CategoryID) {
|
|
51
51
|
matches = matches && q.CategoryID?.trim().toLowerCase() === CategoryID.trim().toLowerCase();
|
|
52
52
|
}
|
|
53
|
-
if (
|
|
54
|
-
matches = matches && q.Category?.trim().toLowerCase() ===
|
|
53
|
+
if (CategoryPath) {
|
|
54
|
+
matches = matches && q.Category?.trim().toLowerCase() === CategoryPath.trim().toLowerCase();
|
|
55
55
|
}
|
|
56
56
|
return matches;
|
|
57
57
|
}
|
|
@@ -62,7 +62,7 @@ export class RunQueryResolver {
|
|
|
62
62
|
if (refreshMetadataIfNotFound) {
|
|
63
63
|
// If we didn't find the query, refresh metadata and try again
|
|
64
64
|
await md.Refresh();
|
|
65
|
-
return this.findQuery(QueryID, QueryName, CategoryID,
|
|
65
|
+
return this.findQuery(QueryID, QueryName, CategoryID, CategoryPath, false); // change the refresh flag to false so we don't loop infinitely
|
|
66
66
|
}
|
|
67
67
|
else {
|
|
68
68
|
return null; // No query found and not refreshing metadata
|
|
@@ -76,7 +76,7 @@ export class RunQueryResolver {
|
|
|
76
76
|
async GetQueryData(@Arg('QueryID', () => String) QueryID: string,
|
|
77
77
|
@Ctx() context: AppContext,
|
|
78
78
|
@Arg('CategoryID', () => String, {nullable: true}) CategoryID?: string,
|
|
79
|
-
@Arg('
|
|
79
|
+
@Arg('CategoryPath', () => String, {nullable: true}) CategoryPath?: string,
|
|
80
80
|
@Arg('Parameters', () => GraphQLJSONObject, {nullable: true}) Parameters?: Record<string, any>,
|
|
81
81
|
@Arg('MaxRows', () => Int, {nullable: true}) MaxRows?: number,
|
|
82
82
|
@Arg('StartRow', () => Int, {nullable: true}) StartRow?: number): Promise<RunQueryResultType> {
|
|
@@ -86,7 +86,7 @@ export class RunQueryResolver {
|
|
|
86
86
|
{
|
|
87
87
|
QueryID: QueryID,
|
|
88
88
|
CategoryID: CategoryID,
|
|
89
|
-
|
|
89
|
+
CategoryPath: CategoryPath,
|
|
90
90
|
Parameters: Parameters,
|
|
91
91
|
MaxRows: MaxRows,
|
|
92
92
|
StartRow: StartRow
|
|
@@ -102,7 +102,7 @@ export class RunQueryResolver {
|
|
|
102
102
|
let queryName = result.QueryName;
|
|
103
103
|
if (!queryName) {
|
|
104
104
|
try {
|
|
105
|
-
const queryInfo = await this.findQuery(QueryID, undefined, CategoryID,
|
|
105
|
+
const queryInfo = await this.findQuery(QueryID, undefined, CategoryID, CategoryPath, true);
|
|
106
106
|
if (queryInfo) {
|
|
107
107
|
queryName = queryInfo.Name;
|
|
108
108
|
}
|
|
@@ -128,7 +128,7 @@ export class RunQueryResolver {
|
|
|
128
128
|
async GetQueryDataByName(@Arg('QueryName', () => String) QueryName: string,
|
|
129
129
|
@Ctx() context: AppContext,
|
|
130
130
|
@Arg('CategoryID', () => String, {nullable: true}) CategoryID?: string,
|
|
131
|
-
@Arg('
|
|
131
|
+
@Arg('CategoryPath', () => String, {nullable: true}) CategoryPath?: string,
|
|
132
132
|
@Arg('Parameters', () => GraphQLJSONObject, {nullable: true}) Parameters?: Record<string, any>,
|
|
133
133
|
@Arg('MaxRows', () => Int, {nullable: true}) MaxRows?: number,
|
|
134
134
|
@Arg('StartRow', () => Int, {nullable: true}) StartRow?: number): Promise<RunQueryResultType> {
|
|
@@ -137,7 +137,7 @@ export class RunQueryResolver {
|
|
|
137
137
|
{
|
|
138
138
|
QueryName: QueryName,
|
|
139
139
|
CategoryID: CategoryID,
|
|
140
|
-
|
|
140
|
+
CategoryPath: CategoryPath,
|
|
141
141
|
Parameters: Parameters,
|
|
142
142
|
MaxRows: MaxRows,
|
|
143
143
|
StartRow: StartRow
|
|
@@ -162,7 +162,7 @@ export class RunQueryResolver {
|
|
|
162
162
|
async GetQueryDataSystemUser(@Arg('QueryID', () => String) QueryID: string,
|
|
163
163
|
@Ctx() context: AppContext,
|
|
164
164
|
@Arg('CategoryID', () => String, {nullable: true}) CategoryID?: string,
|
|
165
|
-
@Arg('
|
|
165
|
+
@Arg('CategoryPath', () => String, {nullable: true}) CategoryPath?: string,
|
|
166
166
|
@Arg('Parameters', () => GraphQLJSONObject, {nullable: true}) Parameters?: Record<string, any>,
|
|
167
167
|
@Arg('MaxRows', () => Int, {nullable: true}) MaxRows?: number,
|
|
168
168
|
@Arg('StartRow', () => Int, {nullable: true}) StartRow?: number): Promise<RunQueryResultType> {
|
|
@@ -171,7 +171,7 @@ export class RunQueryResolver {
|
|
|
171
171
|
{
|
|
172
172
|
QueryID: QueryID,
|
|
173
173
|
CategoryID: CategoryID,
|
|
174
|
-
|
|
174
|
+
CategoryPath: CategoryPath,
|
|
175
175
|
Parameters: Parameters,
|
|
176
176
|
MaxRows: MaxRows,
|
|
177
177
|
StartRow: StartRow
|
|
@@ -182,7 +182,7 @@ export class RunQueryResolver {
|
|
|
182
182
|
let queryName = result.QueryName;
|
|
183
183
|
if (!queryName) {
|
|
184
184
|
try {
|
|
185
|
-
const queryInfo = await this.findQuery(QueryID, undefined, CategoryID,
|
|
185
|
+
const queryInfo = await this.findQuery(QueryID, undefined, CategoryID, CategoryPath, true);
|
|
186
186
|
if (queryInfo) {
|
|
187
187
|
queryName = queryInfo.Name;
|
|
188
188
|
}
|
|
@@ -209,7 +209,7 @@ export class RunQueryResolver {
|
|
|
209
209
|
async GetQueryDataByNameSystemUser(@Arg('QueryName', () => String) QueryName: string,
|
|
210
210
|
@Ctx() context: AppContext,
|
|
211
211
|
@Arg('CategoryID', () => String, {nullable: true}) CategoryID?: string,
|
|
212
|
-
@Arg('
|
|
212
|
+
@Arg('CategoryPath', () => String, {nullable: true}) CategoryPath?: string,
|
|
213
213
|
@Arg('Parameters', () => GraphQLJSONObject, {nullable: true}) Parameters?: Record<string, any>,
|
|
214
214
|
@Arg('MaxRows', () => Int, {nullable: true}) MaxRows?: number,
|
|
215
215
|
@Arg('StartRow', () => Int, {nullable: true}) StartRow?: number): Promise<RunQueryResultType> {
|
|
@@ -218,7 +218,7 @@ export class RunQueryResolver {
|
|
|
218
218
|
{
|
|
219
219
|
QueryName: QueryName,
|
|
220
220
|
CategoryID: CategoryID,
|
|
221
|
-
|
|
221
|
+
CategoryPath: CategoryPath,
|
|
222
222
|
Parameters: Parameters,
|
|
223
223
|
MaxRows: MaxRows,
|
|
224
224
|
StartRow: StartRow
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Metadata, RunReport } from '@memberjunction/core';
|
|
1
|
+
import { EntitySaveOptions, Metadata, RunReport } from '@memberjunction/core';
|
|
2
2
|
import { Arg, Ctx, Field, Int, Mutation, ObjectType, Query, Resolver } from 'type-graphql';
|
|
3
3
|
import { AppContext } from '../types.js';
|
|
4
4
|
import { ConversationDetailEntity, ReportEntity } from '@memberjunction/core-entities';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Arg, Ctx, Field, InputType, Mutation, ObjectType, registerEnumType } from 'type-graphql';
|
|
2
|
-
import { AppContext } from '../types.js';
|
|
3
|
-
import { BaseEntity, CompositeKey, LogError, Metadata, RunView, UserInfo } from '@memberjunction/core';
|
|
2
|
+
import { AppContext, UserPayload } from '../types.js';
|
|
3
|
+
import { BaseEntity, CompositeKey, EntityDeleteOptions, EntitySaveOptions, LogError, Metadata, RunView, UserInfo } from '@memberjunction/core';
|
|
4
4
|
import { RequireSystemUser } from '../directives/RequireSystemUser.js';
|
|
5
5
|
import { CompositeKeyInputType, CompositeKeyOutputType } from '../generic/KeyInputOutputTypes.js';
|
|
6
6
|
import { DatasetItemEntity } from '@memberjunction/core-entities';
|
|
@@ -115,7 +115,7 @@ export class SyncDataResolver {
|
|
|
115
115
|
const md = new Metadata();
|
|
116
116
|
const results: ActionItemOutputType[] = [];
|
|
117
117
|
for (const item of items) {
|
|
118
|
-
results.push(await this.SyncSingleItem(item, context, md));
|
|
118
|
+
results.push(await this.SyncSingleItem(item, context, md, context.userPayload));
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
if (await this.DoSyncItemsAffectMetadata(context.userPayload.userRecord, items)) {
|
|
@@ -160,7 +160,7 @@ export class SyncDataResolver {
|
|
|
160
160
|
return false; // didn't find any
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
-
protected async SyncSingleItem(item: ActionItemInputType, context: AppContext, md: Metadata): Promise<ActionItemOutputType> {
|
|
163
|
+
protected async SyncSingleItem(item: ActionItemInputType, context: AppContext, md: Metadata, userPayload: UserPayload): Promise<ActionItemOutputType> {
|
|
164
164
|
const result = new ActionItemOutputType();
|
|
165
165
|
result.AlternateKey = item.AlternateKey;
|
|
166
166
|
result.PrimaryKey = item.PrimaryKey;
|
|
@@ -179,20 +179,20 @@ export class SyncDataResolver {
|
|
|
179
179
|
const fieldValues = item.RecordJSON ? JSON.parse(item.RecordJSON) : {};
|
|
180
180
|
switch (item.Type) {
|
|
181
181
|
case SyncDataActionType.Create:
|
|
182
|
-
await this.SyncSingleItemCreate(entityObject, fieldValues, result);
|
|
182
|
+
await this.SyncSingleItemCreate(entityObject, fieldValues, result, userPayload);
|
|
183
183
|
break;
|
|
184
184
|
case SyncDataActionType.Update:
|
|
185
|
-
await this.SyncSingleItemUpdate(entityObject, pk, ak, fieldValues, result);
|
|
185
|
+
await this.SyncSingleItemUpdate(entityObject, pk, ak, fieldValues, result, userPayload);
|
|
186
186
|
break;
|
|
187
187
|
case SyncDataActionType.CreateOrUpdate:
|
|
188
188
|
// in this case we attempt to load the item first, if it is not possible to load the item, then we create it
|
|
189
|
-
await this.SyncSingleItemCreateOrUpdate(entityObject, pk, ak, fieldValues, result);
|
|
189
|
+
await this.SyncSingleItemCreateOrUpdate(entityObject, pk, ak, fieldValues, result, userPayload);
|
|
190
190
|
break;
|
|
191
191
|
case SyncDataActionType.Delete:
|
|
192
|
-
await this.SyncSingleItemDelete(entityObject, pk, ak, result);
|
|
192
|
+
await this.SyncSingleItemDelete(entityObject, pk, ak, result, userPayload);
|
|
193
193
|
break;
|
|
194
194
|
case SyncDataActionType.DeleteWithFilter:
|
|
195
|
-
await this.SyncSingleItemDeleteWithFilter(item.EntityName, item.DeleteFilter, result, context.userPayload.userRecord);
|
|
195
|
+
await this.SyncSingleItemDeleteWithFilter(item.EntityName, item.DeleteFilter, result, context.userPayload.userRecord, userPayload);
|
|
196
196
|
break;
|
|
197
197
|
default:
|
|
198
198
|
throw new Error('Invalid SyncDataActionType');
|
|
@@ -211,7 +211,7 @@ export class SyncDataResolver {
|
|
|
211
211
|
}
|
|
212
212
|
|
|
213
213
|
|
|
214
|
-
protected async SyncSingleItemDeleteWithFilter(entityName: string, filter: string, result: ActionItemOutputType, user: UserInfo) {
|
|
214
|
+
protected async SyncSingleItemDeleteWithFilter(entityName: string, filter: string, result: ActionItemOutputType, user: UserInfo, userPayload: UserPayload) {
|
|
215
215
|
try {
|
|
216
216
|
// here we will iterate through the result of a RunView on the entityname/filter and delete each matching record
|
|
217
217
|
let overallSuccess: boolean = true;
|
|
@@ -273,30 +273,30 @@ export class SyncDataResolver {
|
|
|
273
273
|
}
|
|
274
274
|
}
|
|
275
275
|
|
|
276
|
-
protected async SyncSingleItemCreateOrUpdate(entityObject: BaseEntity, pk: CompositeKey, ak: CompositeKey, fieldValues: any, result: ActionItemOutputType) {
|
|
276
|
+
protected async SyncSingleItemCreateOrUpdate(entityObject: BaseEntity, pk: CompositeKey, ak: CompositeKey, fieldValues: any, result: ActionItemOutputType, userPayload: UserPayload) {
|
|
277
277
|
if (!pk || pk.KeyValuePairs.length === 0) {
|
|
278
278
|
// no primary key try to load from alt key
|
|
279
279
|
const altKeyResult = await this.LoadFromAlternateKey(entityObject.EntityInfo.Name, ak, entityObject.ContextCurrentUser);
|
|
280
280
|
if (!altKeyResult) {
|
|
281
281
|
// no record found, create a new one
|
|
282
|
-
await this.SyncSingleItemCreate(entityObject, fieldValues, result);
|
|
282
|
+
await this.SyncSingleItemCreate(entityObject, fieldValues, result, userPayload);
|
|
283
283
|
}
|
|
284
284
|
else {
|
|
285
|
-
await this.InnerSyncSingleItemUpdate(altKeyResult, fieldValues, result);
|
|
285
|
+
await this.InnerSyncSingleItemUpdate(altKeyResult, fieldValues, result, userPayload);
|
|
286
286
|
}
|
|
287
287
|
}
|
|
288
288
|
else {
|
|
289
289
|
// have a primary key do the usual load
|
|
290
290
|
if (await entityObject.InnerLoad(pk)) {
|
|
291
|
-
await this.InnerSyncSingleItemUpdate(entityObject, fieldValues, result);
|
|
291
|
+
await this.InnerSyncSingleItemUpdate(entityObject, fieldValues, result, userPayload);
|
|
292
292
|
}
|
|
293
293
|
else {
|
|
294
|
-
await this.SyncSingleItemCreate(entityObject, fieldValues, result);
|
|
294
|
+
await this.SyncSingleItemCreate(entityObject, fieldValues, result, userPayload);
|
|
295
295
|
}
|
|
296
296
|
}
|
|
297
297
|
}
|
|
298
298
|
|
|
299
|
-
protected async SyncSingleItemDelete(entityObject: BaseEntity, pk: CompositeKey, ak: CompositeKey, result: ActionItemOutputType) {
|
|
299
|
+
protected async SyncSingleItemDelete(entityObject: BaseEntity, pk: CompositeKey, ak: CompositeKey, result: ActionItemOutputType, userPayload: UserPayload) {
|
|
300
300
|
if (!pk || pk.KeyValuePairs.length === 0) {
|
|
301
301
|
const altKeyResult = await this.LoadFromAlternateKey(entityObject.EntityInfo.Name, ak, entityObject.ContextCurrentUser);
|
|
302
302
|
if (!altKeyResult) {
|
|
@@ -342,7 +342,7 @@ export class SyncDataResolver {
|
|
|
342
342
|
}
|
|
343
343
|
}
|
|
344
344
|
|
|
345
|
-
protected async SyncSingleItemCreate(entityObject: BaseEntity, fieldValues: any, result: ActionItemOutputType) {
|
|
345
|
+
protected async SyncSingleItemCreate(entityObject: BaseEntity, fieldValues: any, result: ActionItemOutputType, userPayload: UserPayload) {
|
|
346
346
|
// make sure we strip out the primary key from fieldValues before we pass it in because otherwise it will appear to be an existing record to the BaseEntity
|
|
347
347
|
const noPKValues = {...fieldValues};
|
|
348
348
|
entityObject.EntityInfo.PrimaryKeys.forEach((pk) => {
|
|
@@ -367,7 +367,7 @@ export class SyncDataResolver {
|
|
|
367
367
|
}
|
|
368
368
|
}
|
|
369
369
|
|
|
370
|
-
protected async SyncSingleItemUpdate(entityObject: BaseEntity, pk: CompositeKey, ak: CompositeKey, fieldValues: any, result: ActionItemOutputType) {
|
|
370
|
+
protected async SyncSingleItemUpdate(entityObject: BaseEntity, pk: CompositeKey, ak: CompositeKey, fieldValues: any, result: ActionItemOutputType, userPayload: UserPayload) {
|
|
371
371
|
if (!pk || pk.KeyValuePairs.length === 0) {
|
|
372
372
|
// no pk, attempt to load by alt key
|
|
373
373
|
const altKeyResult = await this.LoadFromAlternateKey(entityObject.EntityInfo.Name, ak, entityObject.ContextCurrentUser);
|
|
@@ -376,11 +376,11 @@ export class SyncDataResolver {
|
|
|
376
376
|
result.ErrorMessage = 'Failed to load the item, it is possible the record with the specified alternate key does not exist';
|
|
377
377
|
}
|
|
378
378
|
else {
|
|
379
|
-
await this.InnerSyncSingleItemUpdate(altKeyResult, fieldValues, result);
|
|
379
|
+
await this.InnerSyncSingleItemUpdate(altKeyResult, fieldValues, result, userPayload);
|
|
380
380
|
}
|
|
381
381
|
}
|
|
382
382
|
else if (await entityObject.InnerLoad(pk)) {
|
|
383
|
-
await this.InnerSyncSingleItemUpdate(entityObject, fieldValues, result);
|
|
383
|
+
await this.InnerSyncSingleItemUpdate(entityObject, fieldValues, result, userPayload);
|
|
384
384
|
}
|
|
385
385
|
else {
|
|
386
386
|
// failed to load the item
|
|
@@ -388,7 +388,7 @@ export class SyncDataResolver {
|
|
|
388
388
|
}
|
|
389
389
|
}
|
|
390
390
|
|
|
391
|
-
protected async InnerSyncSingleItemUpdate(entityObject: BaseEntity, fieldValues: any, result: ActionItemOutputType) {
|
|
391
|
+
protected async InnerSyncSingleItemUpdate(entityObject: BaseEntity, fieldValues: any, result: ActionItemOutputType, userPayload: UserPayload) {
|
|
392
392
|
entityObject.SetMany(fieldValues);
|
|
393
393
|
if (await entityObject.Save()) {
|
|
394
394
|
result.Success = true;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Arg, Ctx, Field, InputType, Mutation, ObjectType, registerEnumType } from 'type-graphql';
|
|
2
|
-
import { AppContext } from '../types.js';
|
|
3
|
-
import { LogError, Metadata, RunView, UserInfo } from '@memberjunction/core';
|
|
2
|
+
import { AppContext, UserPayload } from '../types.js';
|
|
3
|
+
import { EntityDeleteOptions, EntitySaveOptions, LogError, Metadata, RunView, UserInfo } from '@memberjunction/core';
|
|
4
4
|
import { RequireSystemUser } from '../directives/RequireSystemUser.js';
|
|
5
5
|
import { RoleEntity, UserEntity, UserRoleEntity } from '@memberjunction/core-entities';
|
|
6
6
|
import { UserCache } from '@memberjunction/sqlserver-dataprovider';
|
|
@@ -131,9 +131,9 @@ export class SyncRolesAndUsersResolver {
|
|
|
131
131
|
|
|
132
132
|
if (result && result.Success) {
|
|
133
133
|
const currentRoles = result.Results;
|
|
134
|
-
if (await this.DeleteRemovedRoles(currentRoles, roles, context.userPayload.userRecord)) {
|
|
135
|
-
if ( await this.AddNewRoles(currentRoles, roles, context.userPayload.userRecord)) {
|
|
136
|
-
return await this.UpdateExistingRoles(currentRoles, roles, context.userPayload
|
|
134
|
+
if (await this.DeleteRemovedRoles(currentRoles, roles, context.userPayload.userRecord, context.userPayload)) {
|
|
135
|
+
if ( await this.AddNewRoles(currentRoles, roles, context.userPayload.userRecord, context.userPayload)) {
|
|
136
|
+
return await this.UpdateExistingRoles(currentRoles, roles, context.userPayload);
|
|
137
137
|
}
|
|
138
138
|
}
|
|
139
139
|
}
|
|
@@ -145,7 +145,7 @@ export class SyncRolesAndUsersResolver {
|
|
|
145
145
|
}
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
-
protected async UpdateExistingRoles(currentRoles: RoleEntity[], futureRoles: RoleInputType[],
|
|
148
|
+
protected async UpdateExistingRoles(currentRoles: RoleEntity[], futureRoles: RoleInputType[], userPayload: UserPayload): Promise<SyncRolesAndUsersResultType> {
|
|
149
149
|
// go through the future roles and update any that are in the current roles
|
|
150
150
|
const md = new Metadata();
|
|
151
151
|
let ok: boolean = true;
|
|
@@ -160,7 +160,7 @@ export class SyncRolesAndUsersResolver {
|
|
|
160
160
|
return { Success: ok };
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
-
protected async AddNewRoles(currentRoles: RoleEntity[], futureRoles: RoleInputType[], user: UserInfo): Promise<boolean> {
|
|
163
|
+
protected async AddNewRoles(currentRoles: RoleEntity[], futureRoles: RoleInputType[], user: UserInfo, userPayload: UserPayload): Promise<boolean> {
|
|
164
164
|
// go through the future roles and add any that are not in the current roles
|
|
165
165
|
const md = new Metadata();
|
|
166
166
|
let ok: boolean = true;
|
|
@@ -177,7 +177,7 @@ export class SyncRolesAndUsersResolver {
|
|
|
177
177
|
}
|
|
178
178
|
|
|
179
179
|
|
|
180
|
-
protected async DeleteRemovedRoles(currentRoles: RoleEntity[], futureRoles: RoleInputType[], user: UserInfo): Promise<boolean> {
|
|
180
|
+
protected async DeleteRemovedRoles(currentRoles: RoleEntity[], futureRoles: RoleInputType[], user: UserInfo, userPayload: UserPayload): Promise<boolean> {
|
|
181
181
|
const rv = new RunView();
|
|
182
182
|
let ok: boolean = true;
|
|
183
183
|
|
|
@@ -185,7 +185,7 @@ export class SyncRolesAndUsersResolver {
|
|
|
185
185
|
for (const remove of currentRoles) {
|
|
186
186
|
if (!this.IsStandardRole(remove.Name)) {
|
|
187
187
|
if (!futureRoles.find(r => r.Name.trim().toLowerCase() === remove.Name.trim().toLowerCase())) {
|
|
188
|
-
ok = ok && await this.DeleteSingleRole(remove, rv, user);
|
|
188
|
+
ok = ok && await this.DeleteSingleRole(remove, rv, user, userPayload);
|
|
189
189
|
}
|
|
190
190
|
}
|
|
191
191
|
}
|
|
@@ -199,9 +199,10 @@ export class SyncRolesAndUsersResolver {
|
|
|
199
199
|
return this.StandardRoles.find(r => r.toLowerCase() === roleName.toLowerCase()) !== undefined;
|
|
200
200
|
}
|
|
201
201
|
|
|
202
|
-
protected async DeleteSingleRole(role: RoleEntity, rv: RunView, user: UserInfo): Promise<boolean> {
|
|
202
|
+
protected async DeleteSingleRole(role: RoleEntity, rv: RunView, user: UserInfo, userPayload: UserPayload): Promise<boolean> {
|
|
203
203
|
// first, remove all the UserRole records that match this role
|
|
204
204
|
let ok: boolean = true;
|
|
205
|
+
|
|
205
206
|
const r2 = await rv.RunView<UserRoleEntity>({
|
|
206
207
|
EntityName: "User Roles",
|
|
207
208
|
ExtraFilter: "RoleID = '" + role.ID + "'",
|
|
@@ -238,10 +239,10 @@ export class SyncRolesAndUsersResolver {
|
|
|
238
239
|
if (result && result.Success) {
|
|
239
240
|
// go through current users and remove those that are not in the input
|
|
240
241
|
const currentUsers = result.Results;
|
|
241
|
-
if (await this.DeleteRemovedUsers(currentUsers, users, context.userPayload.userRecord)) {
|
|
242
|
-
if (await this.AddNewUsers(currentUsers, users, context.userPayload
|
|
243
|
-
if (await this.UpdateExistingUsers(currentUsers, users, context.userPayload
|
|
244
|
-
if (await this.SyncUserRoles(users, context.userPayload.userRecord)) {
|
|
242
|
+
if (await this.DeleteRemovedUsers(currentUsers, users, context.userPayload.userRecord, context.userPayload)) {
|
|
243
|
+
if (await this.AddNewUsers(currentUsers, users, context.userPayload)) {
|
|
244
|
+
if (await this.UpdateExistingUsers(currentUsers, users, context.userPayload)) {
|
|
245
|
+
if (await this.SyncUserRoles(users, context.userPayload.userRecord, context.userPayload)) {
|
|
245
246
|
return { Success: true };
|
|
246
247
|
}
|
|
247
248
|
}
|
|
@@ -256,9 +257,10 @@ export class SyncRolesAndUsersResolver {
|
|
|
256
257
|
}
|
|
257
258
|
}
|
|
258
259
|
|
|
259
|
-
protected async UpdateExistingUsers(currentUsers: UserEntity[], futureUsers: UserInputType[],
|
|
260
|
+
protected async UpdateExistingUsers(currentUsers: UserEntity[], futureUsers: UserInputType[], userPayload: UserPayload): Promise<boolean> {
|
|
260
261
|
// go through the future users and update any that are in the current users
|
|
261
262
|
let ok: boolean = true;
|
|
263
|
+
|
|
262
264
|
for (const update of futureUsers) {
|
|
263
265
|
const current = currentUsers.find(c => c.Email?.trim().toLowerCase() === update.Email?.trim().toLowerCase());
|
|
264
266
|
if (current) {
|
|
@@ -272,7 +274,7 @@ export class SyncRolesAndUsersResolver {
|
|
|
272
274
|
}
|
|
273
275
|
return ok;
|
|
274
276
|
}
|
|
275
|
-
protected async AddNewUsers(currentUsers: UserEntity[], futureUsers: UserInputType[],
|
|
277
|
+
protected async AddNewUsers(currentUsers: UserEntity[], futureUsers: UserInputType[], userPayload: UserPayload): Promise<boolean> {
|
|
276
278
|
// add users that are not in the current users
|
|
277
279
|
const md = new Metadata();
|
|
278
280
|
let ok: boolean = true;
|
|
@@ -285,7 +287,7 @@ export class SyncRolesAndUsersResolver {
|
|
|
285
287
|
ok = ok && await match.Save();
|
|
286
288
|
}
|
|
287
289
|
else {
|
|
288
|
-
const user = await md.GetEntityObject<UserEntity>("Users",
|
|
290
|
+
const user = await md.GetEntityObject<UserEntity>("Users", userPayload.userRecord);
|
|
289
291
|
user.Name = add.Name;
|
|
290
292
|
user.Type = add.Type;
|
|
291
293
|
user.Email = add.Email;
|
|
@@ -300,7 +302,7 @@ export class SyncRolesAndUsersResolver {
|
|
|
300
302
|
return ok;
|
|
301
303
|
}
|
|
302
304
|
|
|
303
|
-
protected async DeleteRemovedUsers(currentUsers: UserEntity[], futureUsers: UserInputType[], u: UserInfo): Promise<boolean> {
|
|
305
|
+
protected async DeleteRemovedUsers(currentUsers: UserEntity[], futureUsers: UserInputType[], u: UserInfo, userPayload: UserPayload): Promise<boolean> {
|
|
304
306
|
// remove users that are not in the future users
|
|
305
307
|
const rv = new RunView();
|
|
306
308
|
const md = new Metadata();
|
|
@@ -310,16 +312,17 @@ export class SyncRolesAndUsersResolver {
|
|
|
310
312
|
for (const remove of currentUsers) {
|
|
311
313
|
if (remove.Type.trim().toLowerCase() !== 'owner') {
|
|
312
314
|
if (!futureUsers.find(r => r.Email.trim().toLowerCase() === remove.Email.trim().toLowerCase())) {
|
|
313
|
-
ok = ok && await this.DeleteSingleUser(remove, rv, u);
|
|
315
|
+
ok = ok && await this.DeleteSingleUser(remove, rv, u, userPayload);
|
|
314
316
|
}
|
|
315
317
|
}
|
|
316
318
|
}
|
|
317
319
|
return ok;
|
|
318
320
|
}
|
|
319
321
|
|
|
320
|
-
protected async DeleteSingleUser(user: UserEntity, rv: RunView, u: UserInfo): Promise<boolean> {
|
|
322
|
+
protected async DeleteSingleUser(user: UserEntity, rv: RunView, u: UserInfo, userPayload: UserPayload): Promise<boolean> {
|
|
321
323
|
// first, remove all the UserRole records that match this user
|
|
322
324
|
let ok: boolean = true;
|
|
325
|
+
|
|
323
326
|
const r2 = await rv.RunView<UserRoleEntity>({
|
|
324
327
|
EntityName: "User Roles",
|
|
325
328
|
ExtraFilter: "UserID = '" + user.ID + "'",
|
|
@@ -341,7 +344,7 @@ export class SyncRolesAndUsersResolver {
|
|
|
341
344
|
}
|
|
342
345
|
}
|
|
343
346
|
|
|
344
|
-
protected async SyncUserRoles(users: UserInputType[], u: UserInfo): Promise<boolean> {
|
|
347
|
+
protected async SyncUserRoles(users: UserInputType[], u: UserInfo, userPayload: UserPayload): Promise<boolean> {
|
|
345
348
|
// for each user in the users array, make sure there is a User Role that matches. First, get a list of all DATABASE user and roels so we have that for fast lookup in memory
|
|
346
349
|
const rv = new RunView();
|
|
347
350
|
const md = new Metadata();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Arg, Ctx, Field, InputType, Int, Mutation, ObjectType, registerEnumType } from 'type-graphql';
|
|
2
2
|
import { AppContext } from '../types.js';
|
|
3
|
-
import { CompositeKey, KeyValuePair, LogError, Metadata, TransactionVariable, BaseEntity } from '@memberjunction/core';
|
|
3
|
+
import { CompositeKey, KeyValuePair, LogError, Metadata, TransactionVariable, BaseEntity, EntityDeleteOptions, EntitySaveOptions } from '@memberjunction/core';
|
|
4
4
|
import { SafeJSONParse } from '@memberjunction/global';
|
|
5
5
|
|
|
6
6
|
export enum TransactionVariableType {
|
|
@@ -14,9 +14,9 @@ import {
|
|
|
14
14
|
Resolver,
|
|
15
15
|
} from '@memberjunction/server';
|
|
16
16
|
import { UserCache } from '@memberjunction/sqlserver-dataprovider';
|
|
17
|
-
import { UserFavoriteEntity } from '@memberjunction/core-entities';
|
|
18
17
|
|
|
19
18
|
import { UserFavorite_, UserFavoriteResolverBase } from '../generated/generated.js';
|
|
19
|
+
import { GetReadOnlyProvider } from '../util.js';
|
|
20
20
|
|
|
21
21
|
//****************************************************************************
|
|
22
22
|
// INPUT TYPE for User Favorite Queries
|
|
@@ -69,13 +69,15 @@ export class UserFavoriteResult {
|
|
|
69
69
|
@Resolver(UserFavorite_)
|
|
70
70
|
export class UserFavoriteResolver extends UserFavoriteResolverBase {
|
|
71
71
|
@Query(() => [UserFavorite_])
|
|
72
|
-
async UserFavoritesByUserID(@Arg('UserID', () => Int) UserID: number, @Ctx() {
|
|
73
|
-
|
|
72
|
+
async UserFavoritesByUserID(@Arg('UserID', () => Int) UserID: number, @Ctx() { providers, userPayload }: AppContext) {
|
|
73
|
+
const provider = GetReadOnlyProvider(providers, {allowFallbackToReadWrite: true})
|
|
74
|
+
return await this.findBy(provider, 'User Favorites', { UserID }, userPayload.userRecord);
|
|
74
75
|
}
|
|
75
76
|
|
|
76
77
|
@Query(() => [UserFavorite_])
|
|
77
|
-
async UserFavoriteSearchByParams(@Arg('params', () => Int) params: UserFavoriteSearchParams, @Ctx() {
|
|
78
|
-
|
|
78
|
+
async UserFavoriteSearchByParams(@Arg('params', () => Int) params: UserFavoriteSearchParams, @Ctx() { providers, userPayload }: AppContext) {
|
|
79
|
+
const provider = GetReadOnlyProvider(providers, {allowFallbackToReadWrite: true})
|
|
80
|
+
return await this.findBy(provider, 'User Favorites', params, userPayload.userRecord);
|
|
79
81
|
}
|
|
80
82
|
|
|
81
83
|
@Query(() => UserFavoriteResult)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { AppContext, Arg, Ctx, Int, Query, Resolver } from '@memberjunction/server';
|
|
2
2
|
import { User_, UserResolverBase } from '../generated/generated.js';
|
|
3
|
+
import { GetReadOnlyProvider } from '../util.js';
|
|
3
4
|
|
|
4
5
|
@Resolver(User_)
|
|
5
6
|
export class UserResolver extends UserResolverBase {
|
|
@@ -11,22 +12,25 @@ export class UserResolver extends UserResolverBase {
|
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
@Query(() => User_)
|
|
14
|
-
async UserByID(@Arg('ID', () => Int) ID: number, @Ctx() {
|
|
15
|
-
const
|
|
15
|
+
async UserByID(@Arg('ID', () => Int) ID: number, @Ctx() { providers, userPayload }: AppContext) {
|
|
16
|
+
const provider = GetReadOnlyProvider(providers, {allowFallbackToReadWrite: true})
|
|
17
|
+
const retVal = super.safeFirstArrayElement(await this.findBy(provider, 'Users', { ID }, userPayload.userRecord));
|
|
16
18
|
return this.MapFieldNamesToCodeNames('Users', retVal);
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
@Query(() => User_)
|
|
20
|
-
async UserByEmployeeID(@Arg('EmployeeID', () => Int) EmployeeID: number, @Ctx() {
|
|
21
|
-
const
|
|
22
|
+
async UserByEmployeeID(@Arg('EmployeeID', () => Int) EmployeeID: number, @Ctx() { providers, userPayload }: AppContext) {
|
|
23
|
+
const provider = GetReadOnlyProvider(providers, {allowFallbackToReadWrite: true})
|
|
24
|
+
const retVal = super.safeFirstArrayElement(await this.findBy(provider, 'Users', { EmployeeID }, userPayload.userRecord));
|
|
22
25
|
return this.MapFieldNamesToCodeNames('Users', retVal);
|
|
23
26
|
}
|
|
24
27
|
|
|
25
28
|
@Query(() => User_)
|
|
26
|
-
async UserByEmail(@Arg('Email', () => String) Email: string, @Ctx() {
|
|
29
|
+
async UserByEmail(@Arg('Email', () => String) Email: string, @Ctx() { providers, userPayload }: AppContext) {
|
|
27
30
|
// const searchEmail = userEmailMap[Email] ?? Email;
|
|
28
31
|
const searchEmail = Email;
|
|
29
|
-
const
|
|
32
|
+
const provider = GetReadOnlyProvider(providers, {allowFallbackToReadWrite: true})
|
|
33
|
+
const returnVal = super.safeFirstArrayElement(await this.findBy(provider, 'Users', { Email: searchEmail }, userPayload.userRecord));
|
|
30
34
|
return this.MapFieldNamesToCodeNames('Users', returnVal);
|
|
31
35
|
}
|
|
32
36
|
}
|
|
@@ -1,29 +1,33 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
import { Metadata } from '@memberjunction/core';
|
|
2
|
+
import { EntitySaveOptions, Metadata } from '@memberjunction/core';
|
|
3
3
|
import { AppContext, Arg, Ctx, Int, Query, Resolver, UserPayload } from '@memberjunction/server';
|
|
4
4
|
import { UserView_, UserViewResolverBase } from '../generated/generated.js';
|
|
5
5
|
import { UserResolver } from './UserResolver.js';
|
|
6
6
|
import { UserViewEntity, UserViewEntityExtended } from '@memberjunction/core-entities';
|
|
7
|
+
import { GetReadOnlyProvider } from '../util.js';
|
|
7
8
|
|
|
8
9
|
@Resolver(UserView_)
|
|
9
10
|
export class UserViewResolver extends UserViewResolverBase {
|
|
10
11
|
@Query(() => [UserView_])
|
|
11
|
-
async UserViewsByUserID(@Arg('UserID', () => Int) UserID: number, @Ctx() {
|
|
12
|
-
|
|
12
|
+
async UserViewsByUserID(@Arg('UserID', () => Int) UserID: number, @Ctx() { providers, userPayload }: AppContext) {
|
|
13
|
+
const provider = GetReadOnlyProvider(providers, {allowFallbackToReadWrite: true})
|
|
14
|
+
return await this.findBy(provider, 'User Views', { UserID }, userPayload.userRecord);
|
|
13
15
|
}
|
|
14
16
|
|
|
15
17
|
@Query(() => [UserView_])
|
|
16
18
|
async DefaultViewByUserAndEntity(
|
|
17
19
|
@Arg('UserID', () => Int) UserID: number,
|
|
18
20
|
@Arg('EntityID', () => Int) EntityID: number,
|
|
19
|
-
@Ctx() {
|
|
21
|
+
@Ctx() { providers, userPayload }: AppContext
|
|
20
22
|
) {
|
|
21
|
-
|
|
23
|
+
const provider = GetReadOnlyProvider(providers, {allowFallbackToReadWrite: true})
|
|
24
|
+
return await this.findBy(provider, 'User Views', { UserID, EntityID, IsDefault: true }, userPayload.userRecord);
|
|
22
25
|
}
|
|
23
26
|
|
|
24
27
|
@Query(() => [UserView_])
|
|
25
28
|
async CurrentUserDefaultViewByEntityID(@Arg('EntityID', () => Int) EntityID: number, @Ctx() context: AppContext) {
|
|
26
|
-
|
|
29
|
+
const provider = GetReadOnlyProvider(context.providers, {allowFallbackToReadWrite: true})
|
|
30
|
+
return await this.findBy(provider, 'User Views', {
|
|
27
31
|
UserID: await this.getCurrentUserID(context),
|
|
28
32
|
EntityID,
|
|
29
33
|
IsDefault: true,
|
|
@@ -38,7 +42,8 @@ export class UserViewResolver extends UserViewResolverBase {
|
|
|
38
42
|
|
|
39
43
|
@Query(() => [UserView_])
|
|
40
44
|
async CurrentUserUserViewsByEntityID(@Arg('EntityID', () => Int) EntityID: number, @Ctx() context: AppContext) {
|
|
41
|
-
|
|
45
|
+
const provider = GetReadOnlyProvider(context.providers, {allowFallbackToReadWrite: true})
|
|
46
|
+
return this.findBy(provider, 'User Views', { UserID: await this.getCurrentUserID(context), EntityID}, context.userPayload.userRecord);
|
|
42
47
|
}
|
|
43
48
|
|
|
44
49
|
@Query(() => [UserView_])
|
|
@@ -52,6 +57,7 @@ export class UserViewResolver extends UserViewResolverBase {
|
|
|
52
57
|
const viewEntity = <UserViewEntityExtended>await md.GetEntityObject('User Views', u);
|
|
53
58
|
await viewEntity.Load(ID);
|
|
54
59
|
viewEntity.UpdateWhereClause();
|
|
60
|
+
|
|
55
61
|
if (await viewEntity.Save()) {
|
|
56
62
|
return viewEntity.GetAll();
|
|
57
63
|
} else {
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { LogStatus, LogError } from '@memberjunction/core';
|
|
2
|
-
import { UserCache } from '@memberjunction/sqlserver-dataprovider';
|
|
2
|
+
import { SQLServerDataProvider, SQLServerProviderConfigData, UserCache } from '@memberjunction/sqlserver-dataprovider';
|
|
3
3
|
import { GetReadWriteDataSource } from '../util.js';
|
|
4
4
|
import { AskSkipResolver } from '../resolvers/AskSkipResolver.js';
|
|
5
|
-
import { DataSourceInfo } from '../types.js';
|
|
5
|
+
import { AppContext, DataSourceInfo } from '../types.js';
|
|
6
6
|
import { getSystemUser } from '../auth/index.js';
|
|
7
7
|
import { BaseSingleton } from '@memberjunction/global';
|
|
8
|
+
import { mj_core_schema } from '../config.js';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* A simple scheduler for the Skip AI learning cycle
|
|
@@ -89,7 +90,11 @@ export class LearningCycleScheduler extends BaseSingleton<LearningCycleScheduler
|
|
|
89
90
|
}
|
|
90
91
|
|
|
91
92
|
// Create context for the resolver
|
|
92
|
-
const
|
|
93
|
+
const config = new SQLServerProviderConfigData(dataSource, mj_core_schema, 0, undefined, undefined, false);
|
|
94
|
+
const p = new SQLServerDataProvider();
|
|
95
|
+
await p.Config(config);
|
|
96
|
+
|
|
97
|
+
const context: AppContext = {
|
|
93
98
|
dataSource: dataSource,
|
|
94
99
|
dataSources: this.dataSources,
|
|
95
100
|
userPayload: {
|
|
@@ -97,7 +102,8 @@ export class LearningCycleScheduler extends BaseSingleton<LearningCycleScheduler
|
|
|
97
102
|
sessionId: `scheduler_${Date.now()}`,
|
|
98
103
|
userRecord: systemUser,
|
|
99
104
|
isSystemUser: true
|
|
100
|
-
}
|
|
105
|
+
},
|
|
106
|
+
providers: [{provider: p, type: 'Read-Write'}]
|
|
101
107
|
};
|
|
102
108
|
|
|
103
109
|
// Execute the learning cycle
|
package/src/types.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { UserInfo } from '@memberjunction/core';
|
|
1
|
+
import { DatabaseProviderBase, UserInfo } from '@memberjunction/core';
|
|
2
2
|
import { UserViewEntity } from '@memberjunction/core-entities';
|
|
3
3
|
import { GraphQLSchema } from 'graphql';
|
|
4
4
|
import { PubSubEngine } from 'type-graphql';
|
|
5
5
|
import sql from 'mssql';
|
|
6
6
|
import { getSystemUser } from './auth/index.js';
|
|
7
7
|
import { MJEvent, MJEventType, MJGlobal } from '@memberjunction/global';
|
|
8
|
+
import { SQLServerDataProvider } from '@memberjunction/sqlserver-dataprovider';
|
|
8
9
|
|
|
9
10
|
export type UserPayload = {
|
|
10
11
|
email: string;
|
|
@@ -28,8 +29,18 @@ export type AppContext = {
|
|
|
28
29
|
* Array of connection pools that have additional information about their intended use e.g. Admin, Read-Write, Read-Only.
|
|
29
30
|
*/
|
|
30
31
|
dataSources: DataSourceInfo[];
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Per-request DatabaseProviderBase instances
|
|
35
|
+
*/
|
|
36
|
+
providers: Array<ProviderInfo>;
|
|
31
37
|
};
|
|
32
38
|
|
|
39
|
+
export class ProviderInfo {
|
|
40
|
+
provider: DatabaseProviderBase;
|
|
41
|
+
type: 'Admin' | 'Read-Write' | 'Read-Only' | 'Other';
|
|
42
|
+
}
|
|
43
|
+
|
|
33
44
|
export class DataSourceInfo {
|
|
34
45
|
dataSource: sql.ConnectionPool;
|
|
35
46
|
host: string;
|
|
@@ -56,7 +67,7 @@ export type DirectiveBuilder = {
|
|
|
56
67
|
|
|
57
68
|
export type RunViewGenericParams = {
|
|
58
69
|
viewInfo: UserViewEntity;
|
|
59
|
-
|
|
70
|
+
provider: DatabaseProviderBase;
|
|
60
71
|
extraFilter: string;
|
|
61
72
|
orderBy: string;
|
|
62
73
|
userSearchString: string;
|
|
@@ -69,8 +80,7 @@ export type RunViewGenericParams = {
|
|
|
69
80
|
forceAuditLog?: boolean;
|
|
70
81
|
auditLogDescription?: string;
|
|
71
82
|
resultType?: string;
|
|
72
|
-
userPayload?: UserPayload;
|
|
73
|
-
pubSub: PubSubEngine;
|
|
83
|
+
userPayload?: UserPayload;
|
|
74
84
|
};
|
|
75
85
|
|
|
76
86
|
|