@solidstarters/solid-core 1.2.64 → 1.2.67

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.
Files changed (81) hide show
  1. package/dist/controllers/chatter-message.controller.d.ts +1 -2
  2. package/dist/controllers/chatter-message.controller.d.ts.map +1 -1
  3. package/dist/controllers/chatter-message.controller.js +3 -7
  4. package/dist/controllers/chatter-message.controller.js.map +1 -1
  5. package/dist/decorators/active-user.decorator.d.ts.map +1 -1
  6. package/dist/decorators/active-user.decorator.js.map +1 -1
  7. package/dist/decorators/solid-request-context.decorator.d.ts.map +1 -1
  8. package/dist/decorators/solid-request-context.decorator.js.map +1 -1
  9. package/dist/guards/access-token.guard.d.ts +3 -1
  10. package/dist/guards/access-token.guard.d.ts.map +1 -1
  11. package/dist/guards/access-token.guard.js +6 -2
  12. package/dist/guards/access-token.guard.js.map +1 -1
  13. package/dist/index.d.ts +0 -1
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +0 -1
  16. package/dist/index.js.map +1 -1
  17. package/dist/providers/list-of-values-selection-providers.service.d.ts.map +1 -1
  18. package/dist/providers/list-of-values-selection-providers.service.js +15 -5
  19. package/dist/providers/list-of-values-selection-providers.service.js.map +1 -1
  20. package/dist/seeders/seed-data/solid-core-metadata.json +9 -51
  21. package/dist/services/authentication.service.d.ts +3 -1
  22. package/dist/services/authentication.service.d.ts.map +1 -1
  23. package/dist/services/authentication.service.js +12 -3
  24. package/dist/services/authentication.service.js.map +1 -1
  25. package/dist/services/chatter-message-details.service.d.ts +1 -3
  26. package/dist/services/chatter-message-details.service.d.ts.map +1 -1
  27. package/dist/services/chatter-message-details.service.js +3 -6
  28. package/dist/services/chatter-message-details.service.js.map +1 -1
  29. package/dist/services/chatter-message.service.d.ts +7 -8
  30. package/dist/services/chatter-message.service.d.ts.map +1 -1
  31. package/dist/services/chatter-message.service.js +28 -19
  32. package/dist/services/chatter-message.service.js.map +1 -1
  33. package/dist/services/crud.service.d.ts +1 -3
  34. package/dist/services/crud.service.d.ts.map +1 -1
  35. package/dist/services/crud.service.js +3 -42
  36. package/dist/services/crud.service.js.map +1 -1
  37. package/dist/services/field-metadata.service.d.ts.map +1 -1
  38. package/dist/services/field-metadata.service.js +23 -11
  39. package/dist/services/field-metadata.service.js.map +1 -1
  40. package/dist/services/model-metadata.service.d.ts.map +1 -1
  41. package/dist/services/model-metadata.service.js +11 -9
  42. package/dist/services/model-metadata.service.js.map +1 -1
  43. package/dist/services/request-context.service.d.ts +4 -4
  44. package/dist/services/request-context.service.d.ts.map +1 -1
  45. package/dist/services/request-context.service.js +6 -10
  46. package/dist/services/request-context.service.js.map +1 -1
  47. package/dist/services/user.service.d.ts +1 -1
  48. package/dist/services/user.service.d.ts.map +1 -1
  49. package/dist/services/user.service.js +2 -2
  50. package/dist/services/user.service.js.map +1 -1
  51. package/dist/solid-core.module.d.ts.map +1 -1
  52. package/dist/solid-core.module.js +6 -2
  53. package/dist/solid-core.module.js.map +1 -1
  54. package/dist/subscribers/audit.subscriber.d.ts +1 -3
  55. package/dist/subscribers/audit.subscriber.d.ts.map +1 -1
  56. package/dist/subscribers/audit.subscriber.js +7 -12
  57. package/dist/subscribers/audit.subscriber.js.map +1 -1
  58. package/dist/tsconfig.tsbuildinfo +1 -1
  59. package/package.json +2 -1
  60. package/src/controllers/chatter-message.controller.ts +1 -2
  61. package/src/decorators/active-user.decorator.ts +1 -0
  62. package/src/decorators/solid-request-context.decorator.ts +2 -1
  63. package/src/guards/access-token.guard.ts +3 -0
  64. package/src/index.ts +0 -1
  65. package/src/providers/list-of-values-selection-providers.service.ts +14 -5
  66. package/src/seeders/seed-data/solid-core-metadata.json +12 -56
  67. package/src/services/authentication.service.ts +16 -4
  68. package/src/services/chatter-message-details.service.ts +1 -3
  69. package/src/services/chatter-message.service.ts +29 -20
  70. package/src/services/crud.service.ts +0 -8
  71. package/src/services/field-metadata.service.ts +23 -12
  72. package/src/services/model-metadata.service.ts +15 -12
  73. package/src/services/request-context.service.ts +5 -6
  74. package/src/services/user.service.ts +6 -6
  75. package/src/solid-core.module.ts +5 -2
  76. package/src/subscribers/audit.subscriber.ts +5 -9
  77. package/dist/services/user-context.service.d.ts +0 -10
  78. package/dist/services/user-context.service.d.ts.map +0 -1
  79. package/dist/services/user-context.service.js +0 -42
  80. package/dist/services/user-context.service.js.map +0 -1
  81. package/src/services/user-context.service.ts +0 -31
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solidstarters/solid-core",
3
- "version": "1.2.64",
3
+ "version": "1.2.67",
4
4
  "description": "This module is a NestJS module containing all the required core providers required by a Solid application",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -51,6 +51,7 @@
51
51
  "mailgen": "^2.0.28",
52
52
  "mongoose": "^8.7.0",
53
53
  "mysql2": "^3.13.0",
54
+ "nestjs-cls": "^5.4.3",
54
55
  "nodemailer": "^6.9.13",
55
56
  "passport": "^0.7.0",
56
57
  "passport-google-oauth2": "^0.2.0",
@@ -98,8 +98,7 @@ export class ChatterMessageController {
98
98
  async postMessage(
99
99
  @Body() postDto: PostChatterMessageDto,
100
100
  @UploadedFiles() files: Array<Express.Multer.File>,
101
- @SolidRequestContextDecorator() solidRequestContext: SolidRequestContextDto
102
101
  ) {
103
- return this.service.postMessage(postDto, solidRequestContext, files);
102
+ return this.service.postMessage(postDto, files);
104
103
  }
105
104
  }
@@ -5,6 +5,7 @@ import { REQUEST_USER_KEY } from "../constants";
5
5
  export const ActiveUser = createParamDecorator(
6
6
  (field: keyof ActiveUserData | undefined, ctx: ExecutionContext) => {
7
7
  const request = ctx.switchToHttp().getRequest();
8
+ // TODO idealiy we should use RequestContextService and getActiveUser method. (Works for async scenarios too)
8
9
  const user: ActiveUserData | undefined = request[REQUEST_USER_KEY];
9
10
  return field ? user?.[field] : user;
10
11
  },
@@ -6,7 +6,8 @@ import { SolidRequestContextDto } from 'src/dtos/solid-request-context.dto';
6
6
  export const SolidRequestContextDecorator = createParamDecorator(
7
7
  (data: unknown, ctx: ExecutionContext): SolidRequestContextDto => {
8
8
  const request = ctx.switchToHttp().getRequest();
9
- const activeUser: ActiveUserData | undefined = request[REQUEST_USER_KEY]; // Get active user
9
+ // TODO idealiy we should use RequestContextService and getActiveUser method. (Works for async scenarios too)
10
+ const activeUser: ActiveUserData | undefined = request[REQUEST_USER_KEY];
10
11
 
11
12
  // Create a new instance of SolidRequestContextDto and stamp user data
12
13
  const solidRequestContext = new SolidRequestContextDto();
@@ -12,6 +12,7 @@ import { ActiveUserData } from '../interfaces/active-user-data.interface';
12
12
  import { jwtConfig } from '../config/iam.config';
13
13
  import { REQUEST_USER_KEY } from "../constants";
14
14
  import { PermissionMetadataService } from '../services/permission-metadata.service';
15
+ import { ClsService } from 'nestjs-cls';
15
16
 
16
17
  @Injectable()
17
18
  export class AccessTokenGuard implements CanActivate {
@@ -20,6 +21,7 @@ export class AccessTokenGuard implements CanActivate {
20
21
  @Inject(jwtConfig.KEY)
21
22
  private readonly jwtConfiguration: ConfigType<typeof jwtConfig>,
22
23
  private readonly permissionsService: PermissionMetadataService,
24
+ private readonly cls: ClsService
23
25
  ) { }
24
26
 
25
27
  async canActivate(context: ExecutionContext): Promise<boolean> {
@@ -40,6 +42,7 @@ export class AccessTokenGuard implements CanActivate {
40
42
  payload.permissions = permissions.map((permission) => permission.name);
41
43
 
42
44
  request[REQUEST_USER_KEY] = payload;
45
+ this.cls.set(REQUEST_USER_KEY, payload);
43
46
  // console.log(`About to set payload in the request user key:`);
44
47
  // console.log(payload);
45
48
  } catch {
package/src/index.ts CHANGED
@@ -228,7 +228,6 @@ export * from './services/security-rule.service'
228
228
  export * from './services/request-context.service'
229
229
  export * from './services/chatter-message.service'
230
230
  export * from './services/chatter-message-details.service'
231
- export * from './services/user-context.service'
232
231
  // Repositories
233
232
  export * from './repository/solid-base.repository'
234
233
  export * from './repository/security-rule.repository'
@@ -34,12 +34,21 @@ export class ListOfValuesSelectionProvider implements ISelectionProvider<ListOfV
34
34
 
35
35
  async values(query: string, ctxt: ListOfValuesProviderContext): Promise<readonly ISelectionProviderValues[]> {
36
36
  const basicFilterQuery = new BasicFilterDto(DEFAULT_LIMIT, 0);
37
- basicFilterQuery.filters = {
38
- type: {
39
- $eq: ctxt.type
40
- }
37
+ if (ctxt.type) {
38
+ basicFilterQuery.filters = {
39
+ type: {
40
+ $eq: ctxt.type
41
+ }
42
+ };
43
+ }
44
+ if (query) {
45
+ basicFilterQuery.filters = {
46
+ ...basicFilterQuery.filters,
47
+ display: {
48
+ $containsi: `%${query}%`
49
+ }
50
+ };
41
51
  }
42
-
43
52
  const lovs = await this.listOfValuesService.find(basicFilterQuery);
44
53
  const selectionValues = lovs.records.map(lov => {
45
54
  return {
@@ -3807,7 +3807,7 @@
3807
3807
  "name": "media-menu-item",
3808
3808
  "sequenceNumber": 3,
3809
3809
  "actionUserKey": "media-root",
3810
- "moduleUserKey": "solid-core",
3810
+ "moduleUserKey": "solid-core",
3811
3811
  "parentMenuItemUserKey": ""
3812
3812
  },
3813
3813
  {
@@ -3980,32 +3980,11 @@
3980
3980
  {
3981
3981
  "attrs": {
3982
3982
  "className": "pi pi-cog",
3983
- "label": "Generate Code"
3984
- },
3985
- "action": {
3986
- "title": "",
3987
- "body": "",
3988
- "confirmBtnLabel": "Generate Code",
3989
- "cancelBtnLabel": "Cancel",
3990
- "customComponent": "GenerateModuleCodeRowAction",
3991
- "customComponentIsSystem": true,
3992
- "endpoint": ""
3993
- }
3994
- }
3995
- ],
3996
- "headerButtons": [
3997
- {
3998
- "attrs": {
3999
- "className": "pi pi-cog",
4000
- "label": "Generate Code"
4001
- },
4002
- "action": {
4003
- "title": "",
4004
- "body": "",
4005
- "confirmBtnLabel": "Generate Code",
4006
- "cancelBtnLabel": "Cancel",
4007
- "customComponent": "GenerateModuleCode",
4008
- "endpoint": ""
3983
+ "label": "Generate Code",
3984
+ "action": "GenerateModuleCodeRowAction",
3985
+ "openInPopup": true,
3986
+ "actionInContextMenu": true,
3987
+ "customComponentIsSystem": true
4009
3988
  }
4010
3989
  }
4011
3990
  ]
@@ -4172,32 +4151,11 @@
4172
4151
  {
4173
4152
  "attrs": {
4174
4153
  "className": "pi pi-cog",
4175
- "label": "Generate Code"
4176
- },
4177
- "action": {
4178
- "title": "",
4179
- "body": "",
4180
- "confirmBtnLabel": "Generate Code",
4181
- "cancelBtnLabel": "Cancel",
4182
- "customComponent": "GenerateModelCodeRowAction",
4154
+ "label": "Generate Code",
4155
+ "action": "GenerateModelCodeRowAction",
4183
4156
  "customComponentIsSystem": true,
4184
- "endpoint": ""
4185
- }
4186
- }
4187
- ],
4188
- "headerButtons": [
4189
- {
4190
- "attrs": {
4191
- "className": "pi pi-cog",
4192
- "label": "Generate Code"
4193
- },
4194
- "action": {
4195
- "title": "",
4196
- "body": "",
4197
- "confirmBtnLabel": "Generate Code",
4198
- "cancelBtnLabel": "Cancel",
4199
- "customComponent": "GenerateModelCode",
4200
- "endpoint": ""
4157
+ "actionInContextMenu": true,
4158
+ "openInPopup": true
4201
4159
  }
4202
4160
  }
4203
4161
  ]
@@ -6046,7 +6004,7 @@
6046
6004
  "attrs": {
6047
6005
  "name": "name",
6048
6006
  "isSearchable": true
6049
- }
6007
+ }
6050
6008
  },
6051
6009
  {
6052
6010
  "type": "field",
@@ -6210,7 +6168,6 @@
6210
6168
  ]
6211
6169
  }
6212
6170
  },
6213
-
6214
6171
  {
6215
6172
  "name": "media-list-view",
6216
6173
  "displayName": "Solid Media Model",
@@ -8673,6 +8630,5 @@
8673
8630
  }
8674
8631
  ],
8675
8632
  "checksums": [],
8676
- "listOfValues": [
8677
- ]
8633
+ "listOfValues": []
8678
8634
  }
@@ -41,6 +41,7 @@ import {
41
41
  } from "../constants";
42
42
  import { SettingService } from './setting.service';
43
43
  import { CreateUserDto } from 'src/dtos/create-user.dto';
44
+ import { RoleMetadataService } from './role-metadata.service';
44
45
 
45
46
  enum LoginProvider {
46
47
  LOCAL = 'local',
@@ -73,6 +74,8 @@ export class AuthenticationService {
73
74
  private readonly smsService: Msg91OTPService,
74
75
  private readonly eventEmitter: EventEmitter2,
75
76
  private readonly settingService: SettingService,
77
+ private readonly roleMetadataService: RoleMetadataService
78
+
76
79
  ) { }
77
80
 
78
81
  async resolveUser(username: string, email: string) {
@@ -145,7 +148,7 @@ export class AuthenticationService {
145
148
  var { user, pwd, autoGeneratedPwd } = await this.populateForSignup<T>(extensionUser, signUpDto);
146
149
  const savedUser = await extensionUserRepo.save(user);
147
150
 
148
- await this.handlePostSignup(savedUser, signUpDto.roles, pwd, autoGeneratedPwd);
151
+ await this.handlePostSignup(savedUser, signUpDto.roles, pwd, autoGeneratedPwd);
149
152
 
150
153
  return savedUser;
151
154
  }
@@ -158,15 +161,23 @@ export class AuthenticationService {
158
161
  }
159
162
  }
160
163
 
161
-
164
+
162
165
  private async populateForSignup<T extends User>(user: T, signUpDto: SignUpDto, isUserActive: boolean = true) {
163
166
  // const user = new User();
167
+
168
+ if (signUpDto.roles && signUpDto.roles.length > 0) {
169
+ for (let i = 0; i < signUpDto.roles.length; i++) {
170
+ const roleName = signUpDto.roles[i];
171
+ await this.roleMetadataService.findRoleByName(roleName);
172
+ }
173
+ }
164
174
  user.username = signUpDto.username;
165
175
  user.email = signUpDto.email;
166
176
  user.fullName = signUpDto.fullName;
167
177
  if (signUpDto.mobile) {
168
178
  user.mobile = signUpDto.mobile;
169
179
  }
180
+
170
181
  // If password has been specified by the user, then we simply create & activate the user based on the configuration parameter "activateUserOnRegistration".
171
182
  let pwd = '';
172
183
  let autoGeneratedPwd = '';
@@ -186,8 +197,9 @@ export class AuthenticationService {
186
197
  return { user, pwd, autoGeneratedPwd };
187
198
  }
188
199
 
189
- private async handlePostSignup(user: User, roles: string[]=[], pwd: string, autoGeneratedPwd: string) {
190
- this.userService.initializeRolesForNewUser(roles, user);
200
+
201
+ private async handlePostSignup(user: User, roles: string[] = [], pwd: string, autoGeneratedPwd: string) {
202
+ await this.userService.initializeRolesForNewUser(roles, user);
191
203
  // Tanay: Adding user password to history table
192
204
  const userPasswordHistory = new UserPasswordHistory();
193
205
  userPasswordHistory.passwordHash = pwd;
@@ -11,7 +11,6 @@ import { FileService } from 'src/services/file.service';
11
11
  import { CrudHelperService } from 'src/services/crud-helper.service';
12
12
 
13
13
  import { ChatterMessageDetails } from '../entities/chatter-message-details.entity';
14
- import { UserContextService } from './user-context.service';
15
14
 
16
15
  @Injectable()
17
16
  export class ChatterMessageDetailsService extends CRUDService<ChatterMessageDetails>{
@@ -27,8 +26,7 @@ export class ChatterMessageDetailsService extends CRUDService<ChatterMessageDeta
27
26
  @InjectRepository(ChatterMessageDetails, 'default')
28
27
  readonly repo: Repository<ChatterMessageDetails>,
29
28
  readonly moduleRef: ModuleRef,
30
- readonly userContextService: UserContextService
31
29
  ) {
32
- super(modelMetadataService, moduleMetadataService, configService, fileService, discoveryService, crudHelperService, entityManager, repo, 'chatterMessageDetails', 'solid-core', moduleRef, userContextService);
30
+ super(modelMetadataService, moduleMetadataService, configService, fileService, discoveryService, crudHelperService, entityManager, repo, 'chatterMessageDetails', 'solid-core', moduleRef);
33
31
  }
34
32
  }
@@ -16,7 +16,7 @@ import { getMediaStorageProvider } from './mediaStorageProviders';
16
16
  import { MediaStorageProviderType } from '../dtos/create-media-storage-provider-metadata.dto';
17
17
  import { ChatterMessageDetails } from '../entities/chatter-message-details.entity';
18
18
  import { ModelMetadata } from 'src/entities/model-metadata.entity';
19
- import { UserContextService } from './user-context.service';
19
+ import { RequestContextService } from './request-context.service';
20
20
  @Injectable()
21
21
  export class ChatterMessageService extends CRUDService<ChatterMessage>{
22
22
  constructor(
@@ -35,24 +35,27 @@ export class ChatterMessageService extends CRUDService<ChatterMessage>{
35
35
  readonly moduleRef: ModuleRef,
36
36
  @InjectRepository(ModelMetadata)
37
37
  private readonly modelMetadataRepo: Repository<ModelMetadata>,
38
- readonly userContextService: UserContextService
38
+ readonly requestContextService: RequestContextService
39
39
  ) {
40
- super(modelMetadataService, moduleMetadataService, configService, fileService, discoveryService, crudHelperService,entityManager, repo, 'chatterMessage', 'solid-core', moduleRef, userContextService);
40
+ super(modelMetadataService, moduleMetadataService, configService, fileService, discoveryService, crudHelperService,entityManager, repo, 'chatterMessage', 'solid-core', moduleRef);
41
41
  }
42
42
 
43
- async postMessage(postDto: PostChatterMessageDto, solidRequestContext: SolidRequestContextDto, files: Express.Multer.File[] = []) {
43
+ async postMessage(postDto: PostChatterMessageDto, files: Express.Multer.File[] = []) {
44
44
  const chatterMessage = new ChatterMessage();
45
45
  chatterMessage.messageType = 'custom';
46
- chatterMessage.messageSubType = postDto.messageSubType || 'general';
46
+ chatterMessage.messageSubType = postDto.messageSubType || 'post_message';
47
47
  chatterMessage.messageBody = postDto.messageBody;
48
48
  chatterMessage.coModelEntityId = postDto.coModelEntityId;
49
49
  chatterMessage.coModelName = postDto.coModelName;
50
50
 
51
- const userId = typeof solidRequestContext.activeUser === 'object'
52
- ? solidRequestContext.activeUser.sub
53
- : solidRequestContext.activeUser;
54
-
55
- chatterMessage.user = { id: userId } as any;
51
+ const activeUser = this.requestContextService.getActiveUser();
52
+
53
+ if (activeUser) {
54
+ const userId = activeUser?.sub;
55
+ chatterMessage.user = { id: userId } as any;
56
+ } else {
57
+ chatterMessage.user = null;
58
+ }
56
59
 
57
60
  const savedMessage = await this.repo.save(chatterMessage);
58
61
 
@@ -81,7 +84,7 @@ export class ChatterMessageService extends CRUDService<ChatterMessage>{
81
84
  return savedMessage;
82
85
  }
83
86
 
84
- async postAuditMessageOnInsert(entity: any, metadata: EntityMetadata, activeUser: any, messageQueue: boolean = false) {
87
+ async postAuditMessageOnInsert(entity: any, metadata: EntityMetadata, messageQueue: boolean = false) {
85
88
  const model = await this.modelMetadataRepo.findOne({
86
89
  where: {
87
90
  displayName: metadata.name
@@ -98,9 +101,12 @@ export class ChatterMessageService extends CRUDService<ChatterMessage>{
98
101
 
99
102
  const auditFields = model.fields.filter(field =>
100
103
  field.enableAuditTracking &&
101
- !['oneToMany', 'mediaSingle', 'mediaMultiple', 'computed', 'richText', 'json'].includes(field.type)
104
+ !['mediaSingle', 'mediaMultiple', 'computed', 'richText', 'json'].includes(field.type) &&
105
+ !(field.type === 'relation' && field.relationType === 'one-to-many')
102
106
  );
103
107
 
108
+ const activeUser = this.requestContextService.getActiveUser();
109
+
104
110
  const chatterMessage = new ChatterMessage();
105
111
  chatterMessage.messageType = 'audit';
106
112
  chatterMessage.messageSubType = 'insert';
@@ -109,7 +115,7 @@ export class ChatterMessageService extends CRUDService<ChatterMessage>{
109
115
  chatterMessage.messageBody = `New ${model.displayName} created`;
110
116
 
111
117
  if (activeUser) {
112
- const userId = typeof activeUser === 'object' ? activeUser.sub : activeUser;
118
+ const userId = activeUser?.sub;
113
119
  chatterMessage.user = { id: userId } as any;
114
120
  } else {
115
121
  chatterMessage.user = null;
@@ -132,7 +138,7 @@ export class ChatterMessageService extends CRUDService<ChatterMessage>{
132
138
  }
133
139
  }
134
140
 
135
- async postAuditMessageOnUpdate(entity: any, metadata: EntityMetadata, databaseEntity: any, activeUser: any, messageQueue: boolean = false) {
141
+ async postAuditMessageOnUpdate(entity: any, metadata: EntityMetadata, databaseEntity: any, messageQueue: boolean = false) {
136
142
  const model = await this.modelMetadataRepo.findOne({
137
143
  where: {
138
144
  displayName: metadata.name
@@ -149,7 +155,8 @@ async postAuditMessageOnUpdate(entity: any, metadata: EntityMetadata, databaseEn
149
155
 
150
156
  const auditFields = model.fields.filter(field =>
151
157
  field.enableAuditTracking &&
152
- !['oneToMany', 'mediaSingle', 'mediaMultiple', 'computed', 'richText', 'json'].includes(field.type)
158
+ !['mediaSingle', 'mediaMultiple', 'computed', 'richText', 'json'].includes(field.type) &&
159
+ !(field.type === 'relation' && field.relationType === 'one-to-many')
153
160
  );
154
161
 
155
162
  const relationFields = auditFields.filter(field =>
@@ -164,16 +171,16 @@ async postAuditMessageOnUpdate(entity: any, metadata: EntityMetadata, databaseEn
164
171
  databaseEntity = populatedEntity;
165
172
  }
166
173
  }
167
-
168
174
  const changedFields = auditFields.filter(field => {
169
175
  const newValue = entity[field.name];
170
176
  const oldValue = databaseEntity[field.name];
171
177
  return this.hasValueChanged(newValue, oldValue);
172
178
  });
173
-
179
+
174
180
  if (changedFields.length === 0) {
175
181
  return;
176
182
  }
183
+ const activeUser = this.requestContextService.getActiveUser();
177
184
 
178
185
  const chatterMessage = new ChatterMessage();
179
186
  chatterMessage.messageType = 'audit';
@@ -183,7 +190,7 @@ async postAuditMessageOnUpdate(entity: any, metadata: EntityMetadata, databaseEn
183
190
  chatterMessage.messageBody = `${model.displayName} updated`;
184
191
 
185
192
  if (activeUser) {
186
- const userId = typeof activeUser === 'object' ? activeUser.sub : activeUser;
193
+ const userId = activeUser?.sub;
187
194
  chatterMessage.user = { id: userId } as any;
188
195
  } else {
189
196
  chatterMessage.user = null;
@@ -203,7 +210,7 @@ async postAuditMessageOnUpdate(entity: any, metadata: EntityMetadata, databaseEn
203
210
  }
204
211
  }
205
212
 
206
- async postAuditMessageOnDelete(entity: any, metadata: EntityMetadata, databaseEntity: any, activeUser: any, messageQueue: boolean = false) {
213
+ async postAuditMessageOnDelete(entity: any, metadata: EntityMetadata, databaseEntity: any, messageQueue: boolean = false) {
207
214
  const model = await this.modelMetadataRepo.findOne({
208
215
  where: {
209
216
  displayName: metadata.name
@@ -225,8 +232,10 @@ async postAuditMessageOnDelete(entity: any, metadata: EntityMetadata, databaseEn
225
232
  chatterMessage.coModelName = model.singularName;
226
233
  chatterMessage.messageBody = `${model.displayName} deleted`;
227
234
 
235
+ const activeUser = this.requestContextService.getActiveUser();
236
+
228
237
  if (activeUser) {
229
- const userId = typeof activeUser === 'object' ? activeUser.sub : activeUser;
238
+ const userId = activeUser?.sub;
230
239
  chatterMessage.user = { id: userId } as any;
231
240
  } else {
232
241
  chatterMessage.user = null;
@@ -34,7 +34,6 @@ import { FileService } from "./file.service";
34
34
  import { getMediaStorageProvider } from "./mediaStorageProviders";
35
35
  import { ModelMetadataService } from "./model-metadata.service";
36
36
  import { ModuleMetadataService } from "./module-metadata.service";
37
- import { UserContextService } from "./user-context.service";
38
37
  const DEFAULT_LIMIT = 10;
39
38
  const DEFAULT_OFFSET = 0;
40
39
  export class CRUDService<T> { // Add two generic value i.e Person,CreatePersonDto, so we get the proper types in our service
@@ -51,7 +50,6 @@ export class CRUDService<T> { // Add two generic value i.e Person,CreatePersonDt
51
50
  readonly modelName: string,
52
51
  readonly moduleName: string,
53
52
  readonly moduleRef: ModuleRef,
54
- @Optional() readonly userContextService?: UserContextService
55
53
  //We can just have the Model Entity here
56
54
  ) { }
57
55
 
@@ -67,9 +65,6 @@ export class CRUDService<T> { // Add two generic value i.e Person,CreatePersonDt
67
65
  // Check wheather user has create permission for model
68
66
  if (solidRequestContext.activeUser) {
69
67
  const hasPermission = this.crudHelperService.hasCreatePermissionOnModel(solidRequestContext.activeUser, model.singularName);
70
- if (this.userContextService) {
71
- this.userContextService.setUser(solidRequestContext.activeUser);
72
- }
73
68
  if (!hasPermission) {
74
69
  throw new BadRequestException('Forbidden');
75
70
  }
@@ -164,9 +159,6 @@ export class CRUDService<T> { // Add two generic value i.e Person,CreatePersonDt
164
159
  // Check wheather user has update permission for model
165
160
  if (solidRequestContext.activeUser) {
166
161
  const hasPermission = this.crudHelperService.hasUpdatePermissionOnModel(solidRequestContext.activeUser, model.singularName);
167
- if (this.userContextService) {
168
- this.userContextService.setUser(solidRequestContext.activeUser);
169
- }
170
162
  if (!hasPermission) {
171
163
  throw new BadRequestException('Forbidden');
172
164
  }
@@ -503,6 +503,7 @@ export class FieldMetadataService {
503
503
  "encryptionType",
504
504
  "decryptWhen",
505
505
  "columnName",
506
+ "enableAuditTracking"
506
507
  ];
507
508
 
508
509
  case SolidFieldType.bigint:
@@ -521,7 +522,8 @@ export class FieldMetadataService {
521
522
  "encrypt",
522
523
  "encryptionType",
523
524
  "decryptWhen",
524
- "columnName"
525
+ "columnName",
526
+ "enableAuditTracking"
525
527
  ];
526
528
 
527
529
  // case SolidFieldType.float:
@@ -560,7 +562,8 @@ export class FieldMetadataService {
560
562
  "encrypt",
561
563
  "encryptionType",
562
564
  "decryptWhen",
563
- "columnName"
565
+ "columnName",
566
+ "enableAuditTracking"
564
567
  ];
565
568
 
566
569
  case SolidFieldType.shortText:
@@ -582,7 +585,8 @@ export class FieldMetadataService {
582
585
  "encryptionType",
583
586
  "decryptWhen",
584
587
  "columnName",
585
- "isUserKey"
588
+ "isUserKey",
589
+ "enableAuditTracking"
586
590
  ];
587
591
 
588
592
  case SolidFieldType.longtext:
@@ -665,7 +669,8 @@ export class FieldMetadataService {
665
669
  "encrypt",
666
670
  "encryptionType",
667
671
  "decryptWhen",
668
- "columnName"
672
+ "columnName",
673
+ "enableAuditTracking"
669
674
  ];
670
675
 
671
676
  case SolidFieldType.date:
@@ -684,7 +689,8 @@ export class FieldMetadataService {
684
689
  "encrypt",
685
690
  "encryptionType",
686
691
  "decryptWhen",
687
- "columnName"
692
+ "columnName",
693
+ "enableAuditTracking"
688
694
  ];
689
695
 
690
696
  case SolidFieldType.datetime:
@@ -703,7 +709,8 @@ export class FieldMetadataService {
703
709
  "encrypt",
704
710
  "encryptionType",
705
711
  "decryptWhen",
706
- "columnName"
712
+ "columnName",
713
+ "enableAuditTracking"
707
714
  ];
708
715
 
709
716
  case SolidFieldType.time:
@@ -722,7 +729,8 @@ export class FieldMetadataService {
722
729
  "encrypt",
723
730
  "encryptionType",
724
731
  "decryptWhen",
725
- "columnName"
732
+ "columnName",
733
+ "enableAuditTracking"
726
734
  ];
727
735
 
728
736
  case SolidFieldType.relation:
@@ -750,7 +758,8 @@ export class FieldMetadataService {
750
758
  "columnName",
751
759
  "relationJoinTableName",
752
760
  "isRelationManyToManyOwner",
753
- "relationFieldFixedFilter"
761
+ "relationFieldFixedFilter",
762
+ "enableAuditTracking"
754
763
  ];
755
764
 
756
765
  case SolidFieldType.mediaSingle:
@@ -812,7 +821,8 @@ export class FieldMetadataService {
812
821
  "encrypt",
813
822
  "encryptionType",
814
823
  "decryptWhen",
815
- "columnName"
824
+ "columnName",
825
+ "enableAuditTracking"
816
826
  ];
817
827
 
818
828
  case SolidFieldType.password:
@@ -855,7 +865,8 @@ export class FieldMetadataService {
855
865
  "encrypt",
856
866
  "encryptionType",
857
867
  "decryptWhen",
858
- "columnName"
868
+ "columnName",
869
+ "enableAuditTracking"
859
870
  ];
860
871
 
861
872
  case SolidFieldType.selectionDynamic:
@@ -877,8 +888,8 @@ export class FieldMetadataService {
877
888
  "encryptionType",
878
889
  "decryptWhen",
879
890
  "columnName",
880
- "isUserKey"
881
-
891
+ "isUserKey",
892
+ "enableAuditTracking"
882
893
  ];
883
894
  case SolidFieldType.computed:
884
895
  return [
@@ -184,16 +184,19 @@ export class ModelMetadataService {
184
184
  relations: {},
185
185
  });
186
186
  createDto['module'] = resolvedModule;
187
+
188
+ if (createDto['parentModelId']) {
189
+ const resolvedParentModel = await this.dataSource
190
+ .getRepository(ModelMetadata)
191
+ .findOne({
192
+ where: {
193
+ id: createDto['parentModelId'],
194
+ },
195
+ relations: {},
196
+ });
197
+ createDto['parentModel'] = resolvedParentModel;
198
+ }
187
199
 
188
- const resolvedParentModel = await this.dataSource
189
- .getRepository(ModelMetadata)
190
- .findOne({
191
- where: {
192
- id: createDto['parentModelId'],
193
- },
194
- relations: {},
195
- });
196
- createDto['parentModel'] = resolvedParentModel;
197
200
  const { fields: fieldsMetadata, ...modelMetaDataWithoutFields } = createDto;
198
201
  const modelMetadata = this.modelMetadataRepo.create(modelMetaDataWithoutFields);
199
202
  let model = await manager.save(modelMetadata);
@@ -515,8 +518,8 @@ export class ModelMetadataService {
515
518
 
516
519
  // Generate the code for models which are linked to fields having an inverse relation
517
520
  const coModelSingularNames = model.fields.
518
- filter(field => field.type === SolidFieldType.relation && field.relationCreateInverse === true)
519
- .map(field => field.relationCoModelSingularName);
521
+ filter(field => field.type === SolidFieldType.relation && field.relationCreateInverse === true)
522
+ .map(field => field.relationCoModelSingularName);
520
523
 
521
524
  for (const singularName of coModelSingularNames) {
522
525
  const coModel = await this.findOneBySingularName(singularName);
@@ -525,7 +528,7 @@ export class ModelMetadataService {
525
528
  dryRun: options.dryRun
526
529
  };
527
530
  await this.generateCode(inverseOptions);
528
- }
531
+ }
529
532
 
530
533
  await this.generateVAMConfig(model.id);
531
534
 
@@ -1,16 +1,15 @@
1
- import { Inject, Injectable, Scope } from "@nestjs/common";
2
- import { REQUEST } from "@nestjs/core";
1
+ import { Injectable } from "@nestjs/common";
2
+ import { ClsService } from "nestjs-cls";
3
3
  import { REQUEST_USER_KEY } from "src/constants";
4
- import { ActiveUserData } from "src/interfaces/active-user-data.interface";
5
4
 
6
- @Injectable({scope: Scope.REQUEST})
5
+ @Injectable()
7
6
  export class RequestContextService {
8
- constructor(@Inject(REQUEST) private readonly request: Request) {
7
+ constructor(private readonly cls: ClsService) {
9
8
  }
10
9
 
11
10
  // This method i.e getActiveUser() will fetch the user from the request object in the context
12
11
  getActiveUser() {
13
- return this.request[REQUEST_USER_KEY] as ActiveUserData| undefined;
12
+ return this.cls.get(REQUEST_USER_KEY);
14
13
  }
15
14
 
16
15
  }