@memberjunction/server 2.111.0 → 2.112.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/dist/agents/skip-agent.d.ts +4 -4
- package/dist/agents/skip-agent.d.ts.map +1 -1
- package/dist/agents/skip-agent.js +808 -951
- package/dist/agents/skip-agent.js.map +1 -1
- package/dist/agents/skip-sdk.d.ts +1 -1
- package/dist/agents/skip-sdk.d.ts.map +1 -1
- package/dist/agents/skip-sdk.js +53 -43
- package/dist/agents/skip-sdk.js.map +1 -1
- package/dist/apolloServer/index.js +1 -1
- package/dist/auth/AuthProviderFactory.d.ts +1 -1
- package/dist/auth/AuthProviderFactory.d.ts.map +1 -1
- package/dist/auth/AuthProviderFactory.js +1 -3
- package/dist/auth/AuthProviderFactory.js.map +1 -1
- package/dist/auth/BaseAuthProvider.d.ts +1 -1
- package/dist/auth/BaseAuthProvider.d.ts.map +1 -1
- package/dist/auth/BaseAuthProvider.js +3 -2
- package/dist/auth/BaseAuthProvider.js.map +1 -1
- package/dist/auth/IAuthProvider.d.ts +1 -1
- package/dist/auth/IAuthProvider.d.ts.map +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/index.d.ts +1 -1
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +6 -6
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/initializeProviders.js +1 -1
- package/dist/auth/initializeProviders.js.map +1 -1
- package/dist/auth/newUsers.d.ts +1 -1
- package/dist/auth/newUsers.d.ts.map +1 -1
- package/dist/auth/newUsers.js +7 -7
- package/dist/auth/newUsers.js.map +1 -1
- package/dist/auth/providers/Auth0Provider.d.ts +1 -1
- package/dist/auth/providers/Auth0Provider.d.ts.map +1 -1
- package/dist/auth/providers/Auth0Provider.js +1 -1
- package/dist/auth/providers/Auth0Provider.js.map +1 -1
- package/dist/auth/providers/CognitoProvider.d.ts +1 -1
- package/dist/auth/providers/CognitoProvider.d.ts.map +1 -1
- package/dist/auth/providers/CognitoProvider.js +3 -6
- package/dist/auth/providers/CognitoProvider.js.map +1 -1
- package/dist/auth/providers/GoogleProvider.d.ts +1 -1
- package/dist/auth/providers/GoogleProvider.d.ts.map +1 -1
- package/dist/auth/providers/GoogleProvider.js +1 -1
- package/dist/auth/providers/GoogleProvider.js.map +1 -1
- package/dist/auth/providers/MSALProvider.d.ts +1 -1
- package/dist/auth/providers/MSALProvider.d.ts.map +1 -1
- package/dist/auth/providers/MSALProvider.js +1 -1
- package/dist/auth/providers/MSALProvider.js.map +1 -1
- package/dist/auth/providers/OktaProvider.d.ts +1 -1
- package/dist/auth/providers/OktaProvider.d.ts.map +1 -1
- package/dist/auth/providers/OktaProvider.js +1 -1
- package/dist/auth/providers/OktaProvider.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +22 -10
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts +1 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +9 -7
- package/dist/context.js.map +1 -1
- package/dist/entitySubclasses/entityPermissions.server.d.ts +1 -1
- package/dist/entitySubclasses/entityPermissions.server.d.ts.map +1 -1
- package/dist/entitySubclasses/entityPermissions.server.js +1 -1
- package/dist/entitySubclasses/entityPermissions.server.js.map +1 -1
- package/dist/generated/generated.d.ts +648 -648
- package/dist/generated/generated.d.ts.map +1 -1
- package/dist/generated/generated.js +2986 -1133
- package/dist/generated/generated.js.map +1 -1
- package/dist/generic/KeyInputOutputTypes.d.ts +1 -1
- package/dist/generic/KeyInputOutputTypes.d.ts.map +1 -1
- package/dist/generic/KeyInputOutputTypes.js +1 -1
- package/dist/generic/KeyInputOutputTypes.js.map +1 -1
- package/dist/generic/ResolverBase.d.ts +1 -1
- package/dist/generic/ResolverBase.d.ts.map +1 -1
- package/dist/generic/ResolverBase.js +15 -10
- package/dist/generic/ResolverBase.js.map +1 -1
- package/dist/generic/RunViewResolver.d.ts +1 -1
- package/dist/generic/RunViewResolver.d.ts.map +1 -1
- package/dist/generic/RunViewResolver.js +15 -15
- package/dist/generic/RunViewResolver.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -9
- package/dist/index.js.map +1 -1
- package/dist/resolvers/ActionResolver.d.ts +2 -2
- package/dist/resolvers/ActionResolver.d.ts.map +1 -1
- package/dist/resolvers/ActionResolver.js +28 -30
- package/dist/resolvers/ActionResolver.js.map +1 -1
- package/dist/resolvers/AskSkipResolver.d.ts +2 -2
- package/dist/resolvers/AskSkipResolver.d.ts.map +1 -1
- package/dist/resolvers/AskSkipResolver.js +60 -50
- package/dist/resolvers/AskSkipResolver.js.map +1 -1
- package/dist/resolvers/ComponentRegistryResolver.d.ts.map +1 -1
- package/dist/resolvers/ComponentRegistryResolver.js +36 -38
- package/dist/resolvers/ComponentRegistryResolver.js.map +1 -1
- package/dist/resolvers/CreateQueryResolver.d.ts +1 -1
- package/dist/resolvers/CreateQueryResolver.d.ts.map +1 -1
- package/dist/resolvers/CreateQueryResolver.js +43 -40
- package/dist/resolvers/CreateQueryResolver.js.map +1 -1
- package/dist/resolvers/DatasetResolver.d.ts.map +1 -1
- package/dist/resolvers/DatasetResolver.js +1 -1
- package/dist/resolvers/DatasetResolver.js.map +1 -1
- package/dist/resolvers/EntityRecordNameResolver.d.ts +1 -1
- package/dist/resolvers/EntityRecordNameResolver.d.ts.map +1 -1
- package/dist/resolvers/EntityRecordNameResolver.js +1 -1
- package/dist/resolvers/EntityRecordNameResolver.js.map +1 -1
- package/dist/resolvers/EntityResolver.d.ts.map +1 -1
- package/dist/resolvers/EntityResolver.js +1 -1
- package/dist/resolvers/EntityResolver.js.map +1 -1
- package/dist/resolvers/FileCategoryResolver.js +1 -1
- package/dist/resolvers/FileCategoryResolver.js.map +1 -1
- package/dist/resolvers/FileResolver.js +1 -1
- package/dist/resolvers/FileResolver.js.map +1 -1
- package/dist/resolvers/GetDataContextDataResolver.d.ts +1 -1
- package/dist/resolvers/GetDataContextDataResolver.d.ts.map +1 -1
- package/dist/resolvers/GetDataContextDataResolver.js +5 -5
- package/dist/resolvers/GetDataContextDataResolver.js.map +1 -1
- package/dist/resolvers/GetDataResolver.d.ts.map +1 -1
- package/dist/resolvers/GetDataResolver.js +8 -6
- package/dist/resolvers/GetDataResolver.js.map +1 -1
- package/dist/resolvers/MergeRecordsResolver.d.ts +3 -3
- package/dist/resolvers/MergeRecordsResolver.d.ts.map +1 -1
- package/dist/resolvers/MergeRecordsResolver.js +3 -3
- package/dist/resolvers/MergeRecordsResolver.js.map +1 -1
- package/dist/resolvers/PotentialDuplicateRecordResolver.d.ts +1 -1
- package/dist/resolvers/PotentialDuplicateRecordResolver.d.ts.map +1 -1
- package/dist/resolvers/PotentialDuplicateRecordResolver.js +1 -1
- package/dist/resolvers/PotentialDuplicateRecordResolver.js.map +1 -1
- package/dist/resolvers/QueryResolver.d.ts.map +1 -1
- package/dist/resolvers/QueryResolver.js +11 -11
- package/dist/resolvers/QueryResolver.js.map +1 -1
- package/dist/resolvers/ReportResolver.js +1 -1
- package/dist/resolvers/ReportResolver.js.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.js +27 -28
- package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
- package/dist/resolvers/RunAIPromptResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIPromptResolver.js +31 -31
- package/dist/resolvers/RunAIPromptResolver.js.map +1 -1
- package/dist/resolvers/RunTemplateResolver.d.ts.map +1 -1
- package/dist/resolvers/RunTemplateResolver.js +9 -9
- package/dist/resolvers/RunTemplateResolver.js.map +1 -1
- package/dist/resolvers/SqlLoggingConfigResolver.d.ts.map +1 -1
- package/dist/resolvers/SqlLoggingConfigResolver.js +10 -10
- package/dist/resolvers/SqlLoggingConfigResolver.js.map +1 -1
- package/dist/resolvers/SyncDataResolver.d.ts +1 -1
- package/dist/resolvers/SyncDataResolver.d.ts.map +1 -1
- package/dist/resolvers/SyncDataResolver.js +15 -14
- package/dist/resolvers/SyncDataResolver.js.map +1 -1
- package/dist/resolvers/SyncRolesUsersResolver.d.ts +1 -1
- package/dist/resolvers/SyncRolesUsersResolver.d.ts.map +1 -1
- package/dist/resolvers/SyncRolesUsersResolver.js +48 -44
- package/dist/resolvers/SyncRolesUsersResolver.js.map +1 -1
- package/dist/resolvers/TaskResolver.d.ts.map +1 -1
- package/dist/resolvers/TaskResolver.js +7 -7
- package/dist/resolvers/TaskResolver.js.map +1 -1
- package/dist/resolvers/TransactionGroupResolver.d.ts +1 -1
- package/dist/resolvers/TransactionGroupResolver.d.ts.map +1 -1
- package/dist/resolvers/TransactionGroupResolver.js +12 -12
- package/dist/resolvers/TransactionGroupResolver.js.map +1 -1
- package/dist/resolvers/UserFavoriteResolver.d.ts +1 -1
- package/dist/resolvers/UserFavoriteResolver.d.ts.map +1 -1
- package/dist/resolvers/UserFavoriteResolver.js +1 -1
- package/dist/resolvers/UserFavoriteResolver.js.map +1 -1
- package/dist/resolvers/UserViewResolver.d.ts.map +1 -1
- package/dist/resolvers/UserViewResolver.js.map +1 -1
- package/dist/rest/EntityCRUDHandler.d.ts +1 -1
- package/dist/rest/EntityCRUDHandler.d.ts.map +1 -1
- package/dist/rest/EntityCRUDHandler.js +14 -16
- package/dist/rest/EntityCRUDHandler.js.map +1 -1
- package/dist/rest/RESTEndpointHandler.d.ts.map +1 -1
- package/dist/rest/RESTEndpointHandler.js +23 -25
- package/dist/rest/RESTEndpointHandler.js.map +1 -1
- package/dist/rest/ViewOperationsHandler.d.ts +1 -1
- package/dist/rest/ViewOperationsHandler.d.ts.map +1 -1
- package/dist/rest/ViewOperationsHandler.js +17 -21
- package/dist/rest/ViewOperationsHandler.js.map +1 -1
- package/dist/scheduler/LearningCycleScheduler.d.ts.map +1 -1
- package/dist/scheduler/LearningCycleScheduler.js.map +1 -1
- package/dist/services/ScheduledJobsService.d.ts.map +1 -1
- package/dist/services/ScheduledJobsService.js +4 -6
- package/dist/services/ScheduledJobsService.js.map +1 -1
- package/dist/services/TaskOrchestrator.d.ts +1 -1
- package/dist/services/TaskOrchestrator.d.ts.map +1 -1
- package/dist/services/TaskOrchestrator.js +30 -30
- package/dist/services/TaskOrchestrator.js.map +1 -1
- package/dist/types.d.ts +3 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +0 -1
- package/dist/types.js.map +1 -1
- package/dist/util.d.ts +1 -1
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +2 -2
- package/dist/util.js.map +1 -1
- package/package.json +36 -37
- package/src/agents/skip-agent.ts +1067 -1200
- package/src/agents/skip-sdk.ts +877 -851
- package/src/apolloServer/index.ts +2 -2
- package/src/auth/AuthProviderFactory.ts +8 -14
- package/src/auth/BaseAuthProvider.ts +5 -4
- package/src/auth/IAuthProvider.ts +2 -2
- package/src/auth/exampleNewUserSubClass.ts +9 -2
- package/src/auth/index.ts +31 -26
- package/src/auth/initializeProviders.ts +3 -3
- package/src/auth/newUsers.ts +166 -134
- package/src/auth/providers/Auth0Provider.ts +5 -5
- package/src/auth/providers/CognitoProvider.ts +7 -10
- package/src/auth/providers/GoogleProvider.ts +4 -5
- package/src/auth/providers/MSALProvider.ts +5 -5
- package/src/auth/providers/OktaProvider.ts +6 -7
- package/src/config.ts +63 -54
- package/src/context.ts +42 -30
- package/src/entitySubclasses/entityPermissions.server.ts +3 -3
- package/src/generated/generated.ts +48130 -39930
- package/src/generic/KeyInputOutputTypes.ts +3 -6
- package/src/generic/ResolverBase.ts +119 -78
- package/src/generic/RunViewResolver.ts +27 -23
- package/src/index.ts +66 -42
- package/src/resolvers/ActionResolver.ts +46 -57
- package/src/resolvers/AskSkipResolver.ts +607 -533
- package/src/resolvers/ComponentRegistryResolver.ts +547 -562
- package/src/resolvers/CreateQueryResolver.ts +683 -655
- package/src/resolvers/DatasetResolver.ts +5 -6
- package/src/resolvers/EntityCommunicationsResolver.ts +1 -1
- package/src/resolvers/EntityRecordNameResolver.ts +9 -5
- package/src/resolvers/EntityResolver.ts +9 -7
- package/src/resolvers/FileCategoryResolver.ts +2 -2
- package/src/resolvers/FileResolver.ts +4 -4
- package/src/resolvers/GetDataContextDataResolver.ts +106 -118
- package/src/resolvers/GetDataResolver.ts +194 -205
- package/src/resolvers/MergeRecordsResolver.ts +5 -5
- package/src/resolvers/PotentialDuplicateRecordResolver.ts +1 -1
- package/src/resolvers/QueryResolver.ts +95 -78
- package/src/resolvers/ReportResolver.ts +2 -2
- package/src/resolvers/RunAIAgentResolver.ts +818 -828
- package/src/resolvers/RunAIPromptResolver.ts +693 -709
- package/src/resolvers/RunTemplateResolver.ts +105 -103
- package/src/resolvers/SqlLoggingConfigResolver.ts +69 -72
- package/src/resolvers/SyncDataResolver.ts +386 -352
- package/src/resolvers/SyncRolesUsersResolver.ts +387 -350
- package/src/resolvers/TaskResolver.ts +110 -115
- package/src/resolvers/TransactionGroupResolver.ts +143 -138
- package/src/resolvers/UserFavoriteResolver.ts +17 -8
- package/src/resolvers/UserViewResolver.ts +17 -12
- package/src/rest/EntityCRUDHandler.ts +291 -268
- package/src/rest/RESTEndpointHandler.ts +782 -776
- package/src/rest/ViewOperationsHandler.ts +191 -195
- package/src/scheduler/LearningCycleScheduler.ts +8 -52
- package/src/services/ScheduledJobsService.ts +129 -132
- package/src/services/TaskOrchestrator.ts +792 -776
- package/src/types.ts +15 -9
- package/src/util.ts +112 -109
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Arg, Ctx, Field, InputType, Mutation, ObjectType, registerEnumType } from 'type-graphql';
|
|
2
2
|
import { AppContext, UserPayload } from '../types.js';
|
|
3
|
-
import { EntityDeleteOptions, EntitySaveOptions, LogError, Metadata, RunView, UserInfo } from '@memberjunction/
|
|
3
|
+
import { EntityDeleteOptions, EntitySaveOptions, LogError, Metadata, RunView, UserInfo } from '@memberjunction/global';
|
|
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';
|
|
@@ -11,403 +11,440 @@ export class SyncRolesAndUsersResultType {
|
|
|
11
11
|
Success: boolean;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
|
|
15
14
|
@InputType()
|
|
16
15
|
export class RoleInputType {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
@Field(() => String)
|
|
21
|
-
Name: string;
|
|
22
|
-
|
|
23
|
-
@Field(() => String, {nullable: true})
|
|
24
|
-
Description: string;
|
|
25
|
-
}
|
|
16
|
+
@Field(() => String)
|
|
17
|
+
ID: string;
|
|
26
18
|
|
|
19
|
+
@Field(() => String)
|
|
20
|
+
Name: string;
|
|
21
|
+
|
|
22
|
+
@Field(() => String, { nullable: true })
|
|
23
|
+
Description: string;
|
|
24
|
+
}
|
|
27
25
|
|
|
28
26
|
export enum UserType {
|
|
29
|
-
Owner =
|
|
30
|
-
User =
|
|
27
|
+
Owner = 'Owner',
|
|
28
|
+
User = 'User',
|
|
31
29
|
}
|
|
32
30
|
|
|
33
31
|
registerEnumType(UserType, {
|
|
34
|
-
name:
|
|
35
|
-
description:
|
|
32
|
+
name: 'UserType', // GraphQL Enum Name
|
|
33
|
+
description: 'Defines whether a user is an Owner or a User',
|
|
36
34
|
});
|
|
37
35
|
|
|
38
36
|
@InputType()
|
|
39
37
|
export class UserInputType {
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
@Field(() => String)
|
|
39
|
+
ID!: string;
|
|
42
40
|
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
@Field(() => String)
|
|
42
|
+
Name!: string;
|
|
45
43
|
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
@Field(() => String)
|
|
45
|
+
Email!: string;
|
|
48
46
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
47
|
+
// the next field needs to have GraphQL enum with only Owner or User being allowed
|
|
48
|
+
@Field(() => UserType)
|
|
49
|
+
Type!: UserType;
|
|
52
50
|
|
|
53
|
-
|
|
54
|
-
|
|
51
|
+
@Field(() => String, { nullable: true })
|
|
52
|
+
FirstName: string;
|
|
55
53
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
@Field(() => String, {nullable: true})
|
|
60
|
-
Title: string;
|
|
54
|
+
@Field(() => String, { nullable: true })
|
|
55
|
+
LastName: string;
|
|
61
56
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
57
|
+
@Field(() => String, { nullable: true })
|
|
58
|
+
Title: string;
|
|
65
59
|
|
|
60
|
+
@Field(() => [RoleInputType], { nullable: true })
|
|
61
|
+
Roles?: RoleInputType[];
|
|
62
|
+
}
|
|
66
63
|
|
|
67
64
|
@InputType()
|
|
68
65
|
export class RolesAndUsersInputType {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
@Field(() => [RoleInputType])
|
|
73
|
-
public Roles: RoleInputType[];
|
|
74
|
-
}
|
|
66
|
+
@Field(() => [UserInputType])
|
|
67
|
+
public Users: UserInputType[];
|
|
75
68
|
|
|
69
|
+
@Field(() => [RoleInputType])
|
|
70
|
+
public Roles: RoleInputType[];
|
|
71
|
+
}
|
|
76
72
|
|
|
77
73
|
export class SyncRolesAndUsersResolver {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
// and will keep going on its own as per the config. This is a
|
|
98
|
-
// special one-time refresh since we made changes here.
|
|
99
|
-
await UserCache.Instance.Refresh(context.dataSource);
|
|
100
|
-
}
|
|
101
|
-
return usersResult;
|
|
102
|
-
}
|
|
103
|
-
else {
|
|
104
|
-
return roleResult;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
catch (err) {
|
|
108
|
-
LogError(err);
|
|
109
|
-
throw new Error('Error syncing roles and users\n\n' + err);
|
|
74
|
+
/**
|
|
75
|
+
* This mutation will sync both the roles and the users, and the user/role relationships in the system with the data provided in the input.
|
|
76
|
+
* Roles are matched by the name (case insensitive) and users are matched by email
|
|
77
|
+
* @param data
|
|
78
|
+
*/
|
|
79
|
+
@RequireSystemUser()
|
|
80
|
+
@Mutation(() => SyncRolesAndUsersResultType)
|
|
81
|
+
async SyncRolesAndUsers(@Arg('data', () => RolesAndUsersInputType) data: RolesAndUsersInputType, @Ctx() context: AppContext) {
|
|
82
|
+
try {
|
|
83
|
+
// first we sync the roles, then the users
|
|
84
|
+
const roleResult = await this.SyncRoles(data.Roles, context);
|
|
85
|
+
if (roleResult?.Success) {
|
|
86
|
+
const usersResult = await this.SyncUsers(data.Users, context);
|
|
87
|
+
if (usersResult?.Success) {
|
|
88
|
+
// refresh the user cache, don't set an auto-refresh
|
|
89
|
+
// interval here becuase that is alreayd done at startup
|
|
90
|
+
// and will keep going on its own as per the config. This is a
|
|
91
|
+
// special one-time refresh since we made changes here.
|
|
92
|
+
await UserCache.Instance.Refresh(context.dataSource);
|
|
110
93
|
}
|
|
94
|
+
return usersResult;
|
|
95
|
+
} else {
|
|
96
|
+
return roleResult;
|
|
97
|
+
}
|
|
98
|
+
} catch (err) {
|
|
99
|
+
LogError(err);
|
|
100
|
+
throw new Error('Error syncing roles and users\n\n' + err);
|
|
111
101
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* This mutation will sync the roles in the system with the data provided in the input, using the role name for matching (case insensitive)
|
|
106
|
+
* @param data
|
|
107
|
+
*/
|
|
108
|
+
@RequireSystemUser()
|
|
109
|
+
@Mutation(() => SyncRolesAndUsersResultType)
|
|
110
|
+
async SyncRoles(
|
|
120
111
|
@Arg('roles', () => [RoleInputType]) roles: RoleInputType[],
|
|
121
112
|
@Ctx() context: AppContext
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
return { Success: false }; // if we get here, something went wrong
|
|
142
|
-
} catch (err) {
|
|
143
|
-
LogError(err);
|
|
144
|
-
throw new Error('Error syncing roles and users\n\n' + err);
|
|
113
|
+
): Promise<SyncRolesAndUsersResultType> {
|
|
114
|
+
try {
|
|
115
|
+
// we iterate through the provided roles and we remove roles that are not in the input and add roles that are new
|
|
116
|
+
// and update roles that already exist
|
|
117
|
+
const rv = new RunView();
|
|
118
|
+
const result = await rv.RunView<RoleEntity>(
|
|
119
|
+
{
|
|
120
|
+
EntityName: 'Roles',
|
|
121
|
+
ResultType: 'entity_object',
|
|
122
|
+
},
|
|
123
|
+
context.userPayload.userRecord
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
if (result && result.Success) {
|
|
127
|
+
const currentRoles = result.Results;
|
|
128
|
+
if (await this.DeleteRemovedRoles(currentRoles, roles, context.userPayload.userRecord, context.userPayload)) {
|
|
129
|
+
if (await this.AddNewRoles(currentRoles, roles, context.userPayload.userRecord, context.userPayload)) {
|
|
130
|
+
return await this.UpdateExistingRoles(currentRoles, roles, context.userPayload);
|
|
131
|
+
}
|
|
145
132
|
}
|
|
146
|
-
|
|
133
|
+
}
|
|
147
134
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
for (const update of futureRoles) {
|
|
154
|
-
const currentRole = currentRoles.find(r => r.Name.trim().toLowerCase() === update.Name.trim().toLowerCase());
|
|
155
|
-
if (currentRole) {
|
|
156
|
-
currentRole.Description = update.Description;
|
|
157
|
-
ok = ok && await currentRole.Save();
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
return { Success: ok };
|
|
135
|
+
return { Success: false }; // if we get here, something went wrong
|
|
136
|
+
} catch (err) {
|
|
137
|
+
LogError(err);
|
|
138
|
+
throw new Error('Error syncing roles and users\n\n' + err);
|
|
161
139
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
protected async UpdateExistingRoles(
|
|
143
|
+
currentRoles: RoleEntity[],
|
|
144
|
+
futureRoles: RoleInputType[],
|
|
145
|
+
userPayload: UserPayload
|
|
146
|
+
): Promise<SyncRolesAndUsersResultType> {
|
|
147
|
+
// go through the future roles and update any that are in the current roles
|
|
148
|
+
const md = new Metadata();
|
|
149
|
+
let ok: boolean = true;
|
|
150
|
+
|
|
151
|
+
for (const update of futureRoles) {
|
|
152
|
+
const currentRole = currentRoles.find((r) => r.Name.trim().toLowerCase() === update.Name.trim().toLowerCase());
|
|
153
|
+
if (currentRole) {
|
|
154
|
+
currentRole.Description = update.Description;
|
|
155
|
+
ok = ok && (await currentRole.Save());
|
|
156
|
+
}
|
|
177
157
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
158
|
+
return { Success: ok };
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
protected async AddNewRoles(
|
|
162
|
+
currentRoles: RoleEntity[],
|
|
163
|
+
futureRoles: RoleInputType[],
|
|
164
|
+
user: UserInfo,
|
|
165
|
+
userPayload: UserPayload
|
|
166
|
+
): Promise<boolean> {
|
|
167
|
+
// go through the future roles and add any that are not in the current roles
|
|
168
|
+
const md = new Metadata();
|
|
169
|
+
let ok: boolean = true;
|
|
170
|
+
|
|
171
|
+
for (const add of futureRoles) {
|
|
172
|
+
if (!currentRoles.find((r) => r.Name.trim().toLowerCase() === add.Name.trim().toLowerCase())) {
|
|
173
|
+
const role = await md.GetEntityObject<RoleEntity>('Roles', user);
|
|
174
|
+
role.Name = add.Name;
|
|
175
|
+
role.Description = add.Description;
|
|
176
|
+
ok = ok && (await role.Save());
|
|
177
|
+
}
|
|
193
178
|
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
if (r2.Success) {
|
|
212
|
-
for (const ur of r2.Results) {
|
|
213
|
-
ok = ok && await ur.Delete(); // remove the user role
|
|
214
|
-
}
|
|
179
|
+
return ok;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
protected async DeleteRemovedRoles(
|
|
183
|
+
currentRoles: RoleEntity[],
|
|
184
|
+
futureRoles: RoleInputType[],
|
|
185
|
+
user: UserInfo,
|
|
186
|
+
userPayload: UserPayload
|
|
187
|
+
): Promise<boolean> {
|
|
188
|
+
const rv = new RunView();
|
|
189
|
+
let ok: boolean = true;
|
|
190
|
+
|
|
191
|
+
// iterate through the existing roles and remove any that are not in the input
|
|
192
|
+
for (const remove of currentRoles) {
|
|
193
|
+
if (!this.IsStandardRole(remove.Name)) {
|
|
194
|
+
if (!futureRoles.find((r) => r.Name.trim().toLowerCase() === remove.Name.trim().toLowerCase())) {
|
|
195
|
+
ok = ok && (await this.DeleteSingleRole(remove, rv, user, userPayload));
|
|
215
196
|
}
|
|
216
|
-
|
|
217
|
-
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return ok;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
public get StandardRoles(): string[] {
|
|
203
|
+
return ['Developer', 'Integration', 'UI'];
|
|
204
|
+
}
|
|
205
|
+
public IsStandardRole(roleName: string): boolean {
|
|
206
|
+
return this.StandardRoles.find((r) => r.toLowerCase() === roleName.toLowerCase()) !== undefined;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
protected async DeleteSingleRole(role: RoleEntity, rv: RunView, user: UserInfo, userPayload: UserPayload): Promise<boolean> {
|
|
210
|
+
// first, remove all the UserRole records that match this role
|
|
211
|
+
let ok: boolean = true;
|
|
212
|
+
|
|
213
|
+
const r2 = await rv.RunView<UserRoleEntity>(
|
|
214
|
+
{
|
|
215
|
+
EntityName: 'User Roles',
|
|
216
|
+
ExtraFilter: "RoleID = '" + role.ID + "'",
|
|
217
|
+
ResultType: 'entity_object',
|
|
218
|
+
},
|
|
219
|
+
user
|
|
220
|
+
);
|
|
221
|
+
if (r2.Success) {
|
|
222
|
+
for (const ur of r2.Results) {
|
|
223
|
+
ok = ok && (await ur.Delete()); // remove the user role
|
|
224
|
+
}
|
|
218
225
|
}
|
|
219
226
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
227
|
+
return ok && role.Delete(); // remove the role
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* This mutation will sync the just the users in the system with the data provided in the input, matches existing users by email
|
|
232
|
+
* @important This method will NOT work if the roles are not already in sync, meaning if User/Role relationships exist in the input data where the Role doesn't already exist in this system the sync will fail
|
|
233
|
+
* @param data
|
|
234
|
+
*/
|
|
235
|
+
@RequireSystemUser()
|
|
236
|
+
@Mutation(() => SyncRolesAndUsersResultType)
|
|
237
|
+
async SyncUsers(
|
|
228
238
|
@Arg('users', () => [UserInputType]) users: UserInputType[],
|
|
229
239
|
@Ctx() context: AppContext
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
240
|
+
): Promise<SyncRolesAndUsersResultType> {
|
|
241
|
+
try {
|
|
242
|
+
// first, we sync up the users and then the user roles.
|
|
243
|
+
// for syncing users we first remove users that are no longer in the input, then we add new users and update existing users
|
|
244
|
+
const rv = new RunView();
|
|
245
|
+
const result = await rv.RunView<UserEntity>(
|
|
246
|
+
{
|
|
247
|
+
EntityName: 'Users',
|
|
248
|
+
ResultType: 'entity_object',
|
|
249
|
+
},
|
|
250
|
+
context.userPayload.userRecord
|
|
251
|
+
);
|
|
252
|
+
if (result && result.Success) {
|
|
253
|
+
// go through current users and remove those that are not in the input
|
|
254
|
+
const currentUsers = result.Results;
|
|
255
|
+
if (await this.DeleteRemovedUsers(currentUsers, users, context.userPayload.userRecord, context.userPayload)) {
|
|
256
|
+
if (await this.AddNewUsers(currentUsers, users, context.userPayload)) {
|
|
257
|
+
if (await this.UpdateExistingUsers(currentUsers, users, context.userPayload)) {
|
|
258
|
+
if (await this.SyncUserRoles(users, context.userPayload.userRecord, context.userPayload)) {
|
|
259
|
+
return { Success: true };
|
|
260
|
+
}
|
|
251
261
|
}
|
|
252
|
-
|
|
253
|
-
return { Success: false }; // if we get here, something went wrong
|
|
254
|
-
} catch (err) {
|
|
255
|
-
LogError(err);
|
|
256
|
-
throw new Error('Error syncing roles and users\n\n' + err);
|
|
262
|
+
}
|
|
257
263
|
}
|
|
258
|
-
|
|
264
|
+
}
|
|
259
265
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
for (const update of futureUsers) {
|
|
265
|
-
const current = currentUsers.find(c => c.Email?.trim().toLowerCase() === update.Email?.trim().toLowerCase());
|
|
266
|
-
if (current) {
|
|
267
|
-
current.Name = update.Name;
|
|
268
|
-
current.Type = update.Type;
|
|
269
|
-
current.FirstName = update.FirstName;
|
|
270
|
-
current.LastName = update.LastName;
|
|
271
|
-
current.Title = update.Title;
|
|
272
|
-
ok = ok && await current.Save();
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
return ok;
|
|
266
|
+
return { Success: false }; // if we get here, something went wrong
|
|
267
|
+
} catch (err) {
|
|
268
|
+
LogError(err);
|
|
269
|
+
throw new Error('Error syncing roles and users\n\n' + err);
|
|
276
270
|
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
user.IsActive = true;
|
|
298
|
-
|
|
299
|
-
ok = ok && await user.Save();
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
return ok;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
protected async UpdateExistingUsers(
|
|
274
|
+
currentUsers: UserEntity[],
|
|
275
|
+
futureUsers: UserInputType[],
|
|
276
|
+
userPayload: UserPayload
|
|
277
|
+
): Promise<boolean> {
|
|
278
|
+
// go through the future users and update any that are in the current users
|
|
279
|
+
let ok: boolean = true;
|
|
280
|
+
|
|
281
|
+
for (const update of futureUsers) {
|
|
282
|
+
const current = currentUsers.find((c) => c.Email?.trim().toLowerCase() === update.Email?.trim().toLowerCase());
|
|
283
|
+
if (current) {
|
|
284
|
+
current.Name = update.Name;
|
|
285
|
+
current.Type = update.Type;
|
|
286
|
+
current.FirstName = update.FirstName;
|
|
287
|
+
current.LastName = update.LastName;
|
|
288
|
+
current.Title = update.Title;
|
|
289
|
+
ok = ok && (await current.Save());
|
|
290
|
+
}
|
|
303
291
|
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
292
|
+
return ok;
|
|
293
|
+
}
|
|
294
|
+
protected async AddNewUsers(currentUsers: UserEntity[], futureUsers: UserInputType[], userPayload: UserPayload): Promise<boolean> {
|
|
295
|
+
// add users that are not in the current users
|
|
296
|
+
const md = new Metadata();
|
|
297
|
+
let ok: boolean = true;
|
|
298
|
+
|
|
299
|
+
for (const add of futureUsers) {
|
|
300
|
+
const match = currentUsers.find((currentUser) => currentUser.Email?.trim().toLowerCase() === add.Email?.trim().toLowerCase());
|
|
301
|
+
if (match) {
|
|
302
|
+
// make sure the IsActive bit is set to true
|
|
303
|
+
match.IsActive = true;
|
|
304
|
+
ok = ok && (await match.Save());
|
|
305
|
+
} else {
|
|
306
|
+
const user = await md.GetEntityObject<UserEntity>('Users', userPayload.userRecord);
|
|
307
|
+
user.Name = add.Name;
|
|
308
|
+
user.Type = add.Type;
|
|
309
|
+
user.Email = add.Email;
|
|
310
|
+
user.FirstName = add.FirstName;
|
|
311
|
+
user.LastName = add.LastName;
|
|
312
|
+
user.Title = add.Title;
|
|
313
|
+
user.IsActive = true;
|
|
314
|
+
|
|
315
|
+
ok = ok && (await user.Save());
|
|
316
|
+
}
|
|
320
317
|
}
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
else {
|
|
341
|
-
// in some cases there are a lot of fkey constraints that prevent the user from being deleted, so we mark the user as inactive instead
|
|
342
|
-
user.IsActive = false;
|
|
343
|
-
return await user.Save() && ok;
|
|
318
|
+
return ok;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
protected async DeleteRemovedUsers(
|
|
322
|
+
currentUsers: UserEntity[],
|
|
323
|
+
futureUsers: UserInputType[],
|
|
324
|
+
u: UserInfo,
|
|
325
|
+
userPayload: UserPayload
|
|
326
|
+
): Promise<boolean> {
|
|
327
|
+
// remove users that are not in the future users
|
|
328
|
+
const rv = new RunView();
|
|
329
|
+
const md = new Metadata();
|
|
330
|
+
|
|
331
|
+
let ok: boolean = true;
|
|
332
|
+
//const tg = await md.CreateTransactionGroup(); HAVING PROBLEMS with this, so skipping for now, I think the entire thing is wrapped in a transaction and that's causing issues with two styles of trans wrappers
|
|
333
|
+
for (const remove of currentUsers) {
|
|
334
|
+
if (remove.Type.trim().toLowerCase() !== 'owner') {
|
|
335
|
+
if (!futureUsers.find((r) => r.Email.trim().toLowerCase() === remove.Email.trim().toLowerCase())) {
|
|
336
|
+
ok = ok && (await this.DeleteSingleUser(remove, rv, u, userPayload));
|
|
344
337
|
}
|
|
338
|
+
}
|
|
345
339
|
}
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
340
|
+
return ok;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
protected async DeleteSingleUser(user: UserEntity, rv: RunView, u: UserInfo, userPayload: UserPayload): Promise<boolean> {
|
|
344
|
+
// first, remove all the UserRole records that match this user
|
|
345
|
+
let ok: boolean = true;
|
|
346
|
+
|
|
347
|
+
const r2 = await rv.RunView<UserRoleEntity>(
|
|
348
|
+
{
|
|
349
|
+
EntityName: 'User Roles',
|
|
350
|
+
ExtraFilter: "UserID = '" + user.ID + "'",
|
|
351
|
+
ResultType: 'entity_object',
|
|
352
|
+
},
|
|
353
|
+
u
|
|
354
|
+
);
|
|
355
|
+
if (r2.Success) {
|
|
356
|
+
for (const ur of r2.Results) {
|
|
357
|
+
//ur.TransactionGroup = tg;
|
|
358
|
+
ok = ok && (await ur.Delete()); // remove the user role
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
if (await user.Delete()) {
|
|
362
|
+
return ok;
|
|
363
|
+
} else {
|
|
364
|
+
// in some cases there are a lot of fkey constraints that prevent the user from being deleted, so we mark the user as inactive instead
|
|
365
|
+
user.IsActive = false;
|
|
366
|
+
return (await user.Save()) && ok;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
protected async SyncUserRoles(users: UserInputType[], u: UserInfo, userPayload: UserPayload): Promise<boolean> {
|
|
371
|
+
// 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
|
|
372
|
+
const rv = new RunView();
|
|
373
|
+
const md = new Metadata();
|
|
374
|
+
|
|
375
|
+
const p1 = rv.RunView<UserEntity>(
|
|
376
|
+
{
|
|
377
|
+
EntityName: 'Users',
|
|
378
|
+
ResultType: 'entity_object',
|
|
379
|
+
},
|
|
380
|
+
u
|
|
381
|
+
);
|
|
382
|
+
const p2 = rv.RunView<RoleEntity>(
|
|
383
|
+
{
|
|
384
|
+
EntityName: 'Roles',
|
|
385
|
+
ResultType: 'entity_object',
|
|
386
|
+
},
|
|
387
|
+
u
|
|
388
|
+
);
|
|
389
|
+
const p3 = rv.RunView<UserRoleEntity>(
|
|
390
|
+
{
|
|
391
|
+
EntityName: 'User Roles',
|
|
392
|
+
ResultType: 'entity_object',
|
|
393
|
+
},
|
|
394
|
+
u
|
|
395
|
+
);
|
|
396
|
+
|
|
397
|
+
// await both
|
|
398
|
+
const [uResult, rResult, urResult] = await Promise.all([p1, p2, p3]);
|
|
399
|
+
|
|
400
|
+
if (uResult.Success && rResult.Success && urResult.Success) {
|
|
401
|
+
// we have the DB users and roles, and user roles
|
|
402
|
+
const dbUsers = uResult.Results;
|
|
403
|
+
const dbRoles = rResult.Results;
|
|
404
|
+
const dbUserRoles = urResult.Results;
|
|
405
|
+
let ok: boolean = true;
|
|
406
|
+
|
|
407
|
+
// now, we can do lookups in memory from those DB roles and Users for their ID values
|
|
408
|
+
// now we will iterate through the users input type and for each role, make sure it is in there
|
|
409
|
+
//const tg = await md.CreateTransactionGroup();
|
|
410
|
+
for (const user of users) {
|
|
411
|
+
const dbUser = dbUsers.find((u) => u.Email.trim().toLowerCase() === user.Email.trim().toLowerCase());
|
|
412
|
+
if (dbUser) {
|
|
413
|
+
for (const role of user.Roles) {
|
|
414
|
+
const dbRole = dbRoles.find((r) => r.Name.trim().toLowerCase() === role.Name.trim().toLowerCase());
|
|
415
|
+
if (dbRole) {
|
|
416
|
+
// now we need to make sure there is a user role that matches this user and role
|
|
417
|
+
if (!dbUserRoles.find((ur) => ur.UserID === dbUser.ID && ur.RoleID === dbRole.ID)) {
|
|
418
|
+
// we need to add a user role
|
|
419
|
+
const ur = await md.GetEntityObject<UserRoleEntity>('User Roles', u);
|
|
420
|
+
ur.UserID = dbUser.ID;
|
|
421
|
+
ur.RoleID = dbRole.ID;
|
|
422
|
+
ok = ok && (await ur.Save());
|
|
423
|
+
}
|
|
405
424
|
}
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
425
|
+
}
|
|
426
|
+
// now, we check for DB user roles that are NOT in the user.Roles property as they are no longer part of the user's roles
|
|
427
|
+
const thisUserDBRoles = dbUserRoles.filter((ur) => ur.UserID === dbUser.ID);
|
|
428
|
+
for (const dbUserRole of thisUserDBRoles) {
|
|
429
|
+
const role = user.Roles.find(
|
|
430
|
+
(r) =>
|
|
431
|
+
r.Name.trim().toLowerCase() ===
|
|
432
|
+
dbRoles
|
|
433
|
+
.find((rr) => rr.ID === dbUserRole.RoleID)
|
|
434
|
+
?.Name.trim()
|
|
435
|
+
.toLowerCase()
|
|
436
|
+
);
|
|
437
|
+
if (!role && !this.IsStandardRole(dbUserRole.Role)) {
|
|
438
|
+
// this user role is no longer in the user's roles, we need to remove it
|
|
439
|
+
//dbUserRole.TransactionGroup = tg;
|
|
440
|
+
ok = ok && (await dbUserRole.Delete()); // remove the user role - we use await for the DELETE, not the save
|
|
441
|
+
}
|
|
442
|
+
}
|
|
410
443
|
}
|
|
444
|
+
}
|
|
445
|
+
return ok;
|
|
446
|
+
} else {
|
|
447
|
+
return false;
|
|
411
448
|
}
|
|
449
|
+
}
|
|
412
450
|
}
|
|
413
|
-
|