@solidstarters/solid-core 1.2.158 → 1.2.159
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/factories/whatsapp.factory.d.ts.map +1 -1
- package/dist/factories/whatsapp.factory.js +1 -1
- package/dist/factories/whatsapp.factory.js.map +1 -1
- package/dist/helpers/index.d.ts +2 -0
- package/dist/helpers/index.d.ts.map +1 -0
- package/dist/helpers/index.js +13 -0
- package/dist/helpers/index.js.map +1 -0
- package/dist/helpers/model-metadata-helper.service.d.ts +5 -1
- package/dist/helpers/model-metadata-helper.service.d.ts.map +1 -1
- package/dist/helpers/model-metadata-helper.service.js +32 -2
- package/dist/helpers/model-metadata-helper.service.js.map +1 -1
- package/dist/helpers/string.helper.d.ts +2 -0
- package/dist/helpers/string.helper.d.ts.map +1 -0
- package/dist/helpers/string.helper.js +10 -0
- package/dist/helpers/string.helper.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/repository/security-rule.repository.d.ts.map +1 -1
- package/dist/repository/security-rule.repository.js +16 -9
- package/dist/repository/security-rule.repository.js.map +1 -1
- package/dist/repository/user.repository.d.ts +12 -0
- package/dist/repository/user.repository.d.ts.map +1 -0
- package/dist/repository/user.repository.js +34 -0
- package/dist/repository/user.repository.js.map +1 -0
- package/dist/seeders/module-metadata-seeder.service.d.ts +12 -12
- package/dist/seeders/module-metadata-seeder.service.d.ts.map +1 -1
- package/dist/seeders/module-metadata-seeder.service.js +31 -13
- package/dist/seeders/module-metadata-seeder.service.js.map +1 -1
- package/dist/seeders/seed-data/solid-core-metadata.json +40 -6
- package/dist/services/chatter-message.service.d.ts +8 -2
- package/dist/services/chatter-message.service.d.ts.map +1 -1
- package/dist/services/chatter-message.service.js +155 -30
- package/dist/services/chatter-message.service.js.map +1 -1
- package/dist/services/crud-helper.service.d.ts +7 -3
- package/dist/services/crud-helper.service.d.ts.map +1 -1
- package/dist/services/crud-helper.service.js +17 -5
- package/dist/services/crud-helper.service.js.map +1 -1
- package/dist/services/user.service.d.ts +3 -2
- package/dist/services/user.service.d.ts.map +1 -1
- package/dist/services/user.service.js +2 -2
- package/dist/services/user.service.js.map +1 -1
- package/dist/services/view-metadata.service.d.ts +3 -1
- package/dist/services/view-metadata.service.d.ts.map +1 -1
- package/dist/services/view-metadata.service.js +5 -2
- package/dist/services/view-metadata.service.js.map +1 -1
- package/dist/solid-core.module.d.ts.map +1 -1
- package/dist/solid-core.module.js +2 -0
- package/dist/solid-core.module.js.map +1 -1
- package/dist/subscribers/audit.subscriber.d.ts +3 -1
- package/dist/subscribers/audit.subscriber.d.ts.map +1 -1
- package/dist/subscribers/audit.subscriber.js +10 -5
- package/dist/subscribers/audit.subscriber.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/factories/whatsapp.factory.ts +2 -1
- package/src/helpers/index.ts +9 -0
- package/src/helpers/model-metadata-helper.service.ts +30 -2
- package/src/helpers/string.helper.ts +4 -0
- package/src/index.ts +1 -0
- package/src/repository/security-rule.repository.ts +25 -12
- package/src/repository/user.repository.ts +17 -0
- package/src/seeders/module-metadata-seeder.service.ts +34 -15
- package/src/seeders/seed-data/solid-core-metadata.json +40 -6
- package/src/services/chatter-message.service.ts +185 -35
- package/src/services/crud-helper.service.ts +24 -6
- package/src/services/user.service.ts +3 -2
- package/src/services/view-metadata.service.ts +3 -1
- package/src/solid-core.module.ts +3 -0
- package/src/subscribers/audit.subscriber.ts +9 -3
|
@@ -18,6 +18,8 @@ import { ChatterMessageDetails } from '../entities/chatter-message-details.entit
|
|
|
18
18
|
import { ModelMetadata } from 'src/entities/model-metadata.entity';
|
|
19
19
|
import { RequestContextService } from './request-context.service';
|
|
20
20
|
import { ChatterMessageRepository } from 'src/repository/chatter-message.repository';
|
|
21
|
+
import { lowerFirst } from 'src/helpers/string.helper';
|
|
22
|
+
import { ModelMetadataHelperService } from 'src/helpers/model-metadata-helper.service';
|
|
21
23
|
@Injectable()
|
|
22
24
|
export class ChatterMessageService extends CRUDService<ChatterMessage>{
|
|
23
25
|
constructor(
|
|
@@ -36,7 +38,8 @@ export class ChatterMessageService extends CRUDService<ChatterMessage>{
|
|
|
36
38
|
readonly moduleRef: ModuleRef,
|
|
37
39
|
@InjectRepository(ModelMetadata)
|
|
38
40
|
private readonly modelMetadataRepo: Repository<ModelMetadata>,
|
|
39
|
-
readonly requestContextService: RequestContextService
|
|
41
|
+
readonly requestContextService: RequestContextService,
|
|
42
|
+
private readonly modelMetadataHelperService: ModelMetadataHelperService,
|
|
40
43
|
) {
|
|
41
44
|
super(modelMetadataService, moduleMetadataService, configService, fileService, discoveryService, crudHelperService,entityManager, repo, 'chatterMessage', 'solid-core', moduleRef);
|
|
42
45
|
}
|
|
@@ -91,7 +94,7 @@ export class ChatterMessageService extends CRUDService<ChatterMessage>{
|
|
|
91
94
|
}
|
|
92
95
|
const model = await this.modelMetadataRepo.findOne({
|
|
93
96
|
where: {
|
|
94
|
-
|
|
97
|
+
singularName: lowerFirst(metadata.name)
|
|
95
98
|
},
|
|
96
99
|
relations: {
|
|
97
100
|
fields: true,
|
|
@@ -142,13 +145,13 @@ export class ChatterMessageService extends CRUDService<ChatterMessage>{
|
|
|
142
145
|
}
|
|
143
146
|
}
|
|
144
147
|
|
|
145
|
-
async postAuditMessageOnUpdate(entity: any, metadata: EntityMetadata, databaseEntity: any, messageQueue: boolean = false) {
|
|
148
|
+
async postAuditMessageOnUpdate(entity: any, metadata: EntityMetadata, databaseEntity: any, updatedColumns: any[] = [], messageQueue: boolean = false) {
|
|
146
149
|
if(!databaseEntity || !entity){
|
|
147
150
|
return;
|
|
148
151
|
}
|
|
149
152
|
const model = await this.modelMetadataRepo.findOne({
|
|
150
153
|
where: {
|
|
151
|
-
|
|
154
|
+
singularName: lowerFirst(metadata.name)
|
|
152
155
|
},
|
|
153
156
|
relations: {
|
|
154
157
|
fields: true,
|
|
@@ -159,34 +162,70 @@ async postAuditMessageOnUpdate(entity: any, metadata: EntityMetadata, databaseEn
|
|
|
159
162
|
if (!model || !model.enableAuditTracking) {
|
|
160
163
|
return;
|
|
161
164
|
}
|
|
165
|
+
|
|
166
|
+
const modelFields = await this.modelMetadataHelperService.loadFieldHierarchy(model.singularName)
|
|
162
167
|
|
|
163
|
-
const auditFields =
|
|
168
|
+
const auditFields = modelFields.filter(field =>
|
|
164
169
|
field.enableAuditTracking &&
|
|
165
170
|
!['mediaSingle', 'mediaMultiple', 'computed', 'richText', 'json'].includes(field.type) &&
|
|
166
171
|
!(field.type === 'relation' && field.relationType === 'one-to-many')
|
|
167
172
|
);
|
|
168
173
|
|
|
169
|
-
const
|
|
170
|
-
|
|
171
|
-
);
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
174
|
+
const updatedFieldNames = new Set(updatedColumns.map(col => col.propertyName));
|
|
175
|
+
|
|
176
|
+
const allNonRelationFields = auditFields.filter(field => field.type !== 'relation');
|
|
177
|
+
const allRelationFields = auditFields.filter(field => field.type === 'relation');
|
|
178
|
+
|
|
179
|
+
let potentialNonRelationFields = [];
|
|
180
|
+
|
|
181
|
+
if (updatedColumns.length > 0) {
|
|
182
|
+
potentialNonRelationFields = allNonRelationFields.filter(field =>
|
|
183
|
+
updatedFieldNames.has(field.name)
|
|
184
|
+
);
|
|
185
|
+
} else {
|
|
186
|
+
potentialNonRelationFields = allNonRelationFields;
|
|
180
187
|
}
|
|
181
|
-
|
|
188
|
+
|
|
189
|
+
const potentialRelationFields = allRelationFields;
|
|
190
|
+
|
|
191
|
+
const changedNonRelationFields = potentialNonRelationFields.filter(field => {
|
|
182
192
|
const newValue = entity[field.name];
|
|
183
193
|
const oldValue = databaseEntity[field.name];
|
|
184
194
|
return this.hasValueChanged(newValue, oldValue);
|
|
185
195
|
});
|
|
196
|
+
|
|
197
|
+
const changedRelationFields = [];
|
|
198
|
+
if (potentialRelationFields.length > 0) {
|
|
199
|
+
const populatedOldEntity = await this.populateRelationFields(databaseEntity, potentialRelationFields, metadata);
|
|
200
|
+
|
|
201
|
+
for (const field of potentialRelationFields) {
|
|
202
|
+
const newValue = entity[field.name];
|
|
203
|
+
const oldValue = populatedOldEntity[field.name];
|
|
204
|
+
|
|
205
|
+
if (this.hasRelationValueChanged(field, newValue, oldValue)) {
|
|
206
|
+
changedRelationFields.push({
|
|
207
|
+
field,
|
|
208
|
+
newValue,
|
|
209
|
+
oldValue
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
const allChangedFields = [
|
|
217
|
+
...changedNonRelationFields.map(field => ({
|
|
218
|
+
field,
|
|
219
|
+
newValue: entity[field.name],
|
|
220
|
+
oldValue: databaseEntity[field.name]
|
|
221
|
+
})),
|
|
222
|
+
...changedRelationFields
|
|
223
|
+
];
|
|
186
224
|
|
|
187
|
-
if (
|
|
225
|
+
if (allChangedFields.length === 0) {
|
|
188
226
|
return;
|
|
189
227
|
}
|
|
228
|
+
|
|
190
229
|
const activeUser = this.requestContextService.getActiveUser();
|
|
191
230
|
|
|
192
231
|
const chatterMessage = new ChatterMessage();
|
|
@@ -205,14 +244,14 @@ async postAuditMessageOnUpdate(entity: any, metadata: EntityMetadata, databaseEn
|
|
|
205
244
|
|
|
206
245
|
const savedMessage = await this.repo.save(chatterMessage);
|
|
207
246
|
|
|
208
|
-
for (const field of
|
|
247
|
+
for (const { field, newValue, oldValue } of allChangedFields) {
|
|
209
248
|
const messageDetail = new ChatterMessageDetails();
|
|
210
249
|
messageDetail.chatterMessage = savedMessage;
|
|
211
250
|
messageDetail.fieldName = field.name;
|
|
212
|
-
messageDetail.oldValue = this.formatFieldValue(field,
|
|
213
|
-
messageDetail.newValue = this.formatFieldValue(field,
|
|
214
|
-
messageDetail.oldValueDisplay = this.formatFieldValueDisplay(field,
|
|
215
|
-
messageDetail.newValueDisplay = this.formatFieldValueDisplay(field,
|
|
251
|
+
messageDetail.oldValue = this.formatFieldValue(field, oldValue);
|
|
252
|
+
messageDetail.newValue = this.formatFieldValue(field, newValue);
|
|
253
|
+
messageDetail.oldValueDisplay = this.formatFieldValueDisplay(field, oldValue);
|
|
254
|
+
messageDetail.newValueDisplay = this.formatFieldValueDisplay(field, newValue);
|
|
216
255
|
await this.chatterMessageDetailsRepo.save(messageDetail);
|
|
217
256
|
}
|
|
218
257
|
}
|
|
@@ -220,7 +259,7 @@ async postAuditMessageOnUpdate(entity: any, metadata: EntityMetadata, databaseEn
|
|
|
220
259
|
async postAuditMessageOnDelete(entity: any, metadata: EntityMetadata, databaseEntity: any, messageQueue: boolean = false) {
|
|
221
260
|
const model = await this.modelMetadataRepo.findOne({
|
|
222
261
|
where: {
|
|
223
|
-
|
|
262
|
+
singularName: lowerFirst(metadata.name)
|
|
224
263
|
},
|
|
225
264
|
relations: {
|
|
226
265
|
fields: true,
|
|
@@ -296,28 +335,139 @@ private formatFieldValueDisplay(field: any, value: any): string {
|
|
|
296
335
|
}
|
|
297
336
|
|
|
298
337
|
private hasValueChanged(newValue: any, oldValue: any): boolean {
|
|
299
|
-
if (
|
|
300
|
-
(newValue === null || newValue === undefined) &&
|
|
301
|
-
(oldValue === null || oldValue === undefined)
|
|
302
|
-
) {
|
|
338
|
+
if (newValue === oldValue) {
|
|
303
339
|
return false;
|
|
304
340
|
}
|
|
305
341
|
|
|
306
|
-
if (newValue === oldValue) {
|
|
342
|
+
if (newValue === null && oldValue === null) {
|
|
307
343
|
return false;
|
|
308
344
|
}
|
|
309
345
|
|
|
310
|
-
if (
|
|
311
|
-
return
|
|
346
|
+
if (newValue === undefined && oldValue === undefined) {
|
|
347
|
+
return false;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
if (newValue && oldValue && typeof newValue === 'object' && typeof oldValue === 'object') {
|
|
351
|
+
if (newValue.id !== undefined && oldValue.id !== undefined) {
|
|
352
|
+
return newValue.id !== oldValue.id;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
if (Array.isArray(newValue) && Array.isArray(oldValue)) {
|
|
356
|
+
if (newValue.length !== oldValue.length) {
|
|
357
|
+
return true;
|
|
358
|
+
}
|
|
359
|
+
const newIds = newValue.map(item => item.id || item).sort();
|
|
360
|
+
const oldIds = oldValue.map(item => item.id || item).sort();
|
|
361
|
+
return JSON.stringify(newIds) !== JSON.stringify(oldIds);
|
|
362
|
+
}
|
|
312
363
|
}
|
|
313
364
|
|
|
314
|
-
if (
|
|
315
|
-
typeof newValue === 'object' && newValue !== null &&
|
|
316
|
-
typeof oldValue === 'object' && oldValue !== null
|
|
317
|
-
) {
|
|
365
|
+
if (Array.isArray(newValue) && Array.isArray(oldValue)) {
|
|
318
366
|
return JSON.stringify(newValue) !== JSON.stringify(oldValue);
|
|
319
367
|
}
|
|
320
368
|
|
|
321
369
|
return true;
|
|
322
370
|
}
|
|
371
|
+
|
|
372
|
+
private hasRelationValueChanged(field: any, newValue: any, oldValue: any): boolean {
|
|
373
|
+
if (newValue === oldValue) {
|
|
374
|
+
return false;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
if ((newValue === null || newValue === undefined) && (oldValue === null || oldValue === undefined)) {
|
|
378
|
+
return false;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
if (field.relationType === 'many-to-one') {
|
|
382
|
+
const newId = this.extractRelationId(newValue);
|
|
383
|
+
const oldId = this.extractRelationId(oldValue);
|
|
384
|
+
return newId !== oldId;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
if (field.relationType === 'many-to-many' || field.relationType === 'manyToMany') {
|
|
388
|
+
const newIds = this.extractRelationIds(newValue);
|
|
389
|
+
const oldIds = this.extractRelationIds(oldValue);
|
|
390
|
+
|
|
391
|
+
if (newIds.length !== oldIds.length) {
|
|
392
|
+
return true;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
newIds.sort();
|
|
396
|
+
oldIds.sort();
|
|
397
|
+
|
|
398
|
+
return JSON.stringify(newIds) !== JSON.stringify(oldIds);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
return this.hasValueChanged(newValue, oldValue);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
private extractRelationId(value: any): any {
|
|
405
|
+
if (value === null || value === undefined) {
|
|
406
|
+
return null;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
if (typeof value === 'string' || typeof value === 'number') {
|
|
410
|
+
return value;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
if (typeof value === 'object' && value.id !== undefined) {
|
|
414
|
+
return value.id;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
return null;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
private extractRelationIds(value: any): any[] {
|
|
421
|
+
if (!Array.isArray(value)) {
|
|
422
|
+
const id = this.extractRelationId(value);
|
|
423
|
+
return id !== null ? [id] : [];
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
return value.map(item => this.extractRelationId(item)).filter(id => id !== null);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
private async populateRelationFields(databaseEntity: any, relationFields: any[], metadata: EntityMetadata): Promise<any> {
|
|
430
|
+
const populatedEntity = { ...databaseEntity };
|
|
431
|
+
|
|
432
|
+
for (const field of relationFields) {
|
|
433
|
+
const relationValue = databaseEntity[field.name];
|
|
434
|
+
|
|
435
|
+
if (relationValue === null || relationValue === undefined) {
|
|
436
|
+
populatedEntity[field.name] = relationValue;
|
|
437
|
+
continue;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
const relationMetadata = metadata.relations.find(rel => rel.propertyName === field.name);
|
|
441
|
+
if (!relationMetadata) {
|
|
442
|
+
populatedEntity[field.name] = relationValue;
|
|
443
|
+
continue;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
const targetEntity = relationMetadata.inverseEntityMetadata || relationMetadata.type;
|
|
447
|
+
|
|
448
|
+
if (field.relationType === 'many-to-one') {
|
|
449
|
+
const relationId = this.extractRelationId(relationValue);
|
|
450
|
+
if (relationId) {
|
|
451
|
+
const relatedEntity = await this.entityManager.findOne(targetEntity as any, {
|
|
452
|
+
where: { id: relationId }
|
|
453
|
+
});
|
|
454
|
+
populatedEntity[field.name] = relatedEntity;
|
|
455
|
+
} else {
|
|
456
|
+
populatedEntity[field.name] = relationValue;
|
|
457
|
+
}
|
|
458
|
+
} else if (field.relationType === 'many-to-many' || field.relationType === 'manyToMany') {
|
|
459
|
+
const relationIds = this.extractRelationIds(relationValue);
|
|
460
|
+
if (relationIds.length > 0) {
|
|
461
|
+
const relatedEntities = await this.entityManager.findByIds(targetEntity as any, relationIds);
|
|
462
|
+
populatedEntity[field.name] = relatedEntities;
|
|
463
|
+
} else {
|
|
464
|
+
populatedEntity[field.name] = relationValue;
|
|
465
|
+
}
|
|
466
|
+
} else {
|
|
467
|
+
populatedEntity[field.name] = relationValue;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
return populatedEntity;
|
|
472
|
+
}
|
|
323
473
|
}
|
|
@@ -6,6 +6,10 @@ import { SolidRegistry } from "src/helpers/solid-registry";
|
|
|
6
6
|
import { Logger } from "@nestjs/common";
|
|
7
7
|
import { ERROR_MESSAGES } from "src/constants/error-messages";
|
|
8
8
|
|
|
9
|
+
export enum FilterCombinator {
|
|
10
|
+
AND = '$and',
|
|
11
|
+
OR = '$or'
|
|
12
|
+
}
|
|
9
13
|
|
|
10
14
|
export class CrudHelperService {
|
|
11
15
|
constructor(
|
|
@@ -24,7 +28,7 @@ export class CrudHelperService {
|
|
|
24
28
|
return orderOptions;
|
|
25
29
|
}
|
|
26
30
|
|
|
27
|
-
|
|
31
|
+
applyFilters(qb: WhereExpressionBuilder, filters: any, alias: string = 'entity', selectQb: SelectQueryBuilder<any>) {
|
|
28
32
|
const normalizedFilters = this.normalizeObjectKeys(filters);
|
|
29
33
|
if (normalizedFilters.$and) {
|
|
30
34
|
normalizedFilters.$and.forEach((andFilter: any) => {
|
|
@@ -157,8 +161,16 @@ export class CrudHelperService {
|
|
|
157
161
|
private hasJoins(queryBuilder: SelectQueryBuilder<any>): boolean {
|
|
158
162
|
return queryBuilder.expressionMap.joinAttributes.length > 0;
|
|
159
163
|
}
|
|
160
|
-
|
|
161
|
-
buildFilterQuery(
|
|
164
|
+
|
|
165
|
+
buildFilterQuery(
|
|
166
|
+
qb: SelectQueryBuilder<any>,
|
|
167
|
+
basicFilterDto: BasicFilterDto,
|
|
168
|
+
entityAlias: string,
|
|
169
|
+
internationalisation?: boolean,
|
|
170
|
+
draftPublishWorkflow?: boolean,
|
|
171
|
+
moduleRef?: any,
|
|
172
|
+
filterCombinator: FilterCombinator = FilterCombinator.AND
|
|
173
|
+
): SelectQueryBuilder<any> { // TODO : Check how to pass a type to SelectQueryBuilder instead of any
|
|
162
174
|
let { limit, offset, showSoftDeleted, filters } = basicFilterDto;
|
|
163
175
|
const { fields, sort, groupBy, populate = [], populateMedia = [], locale, status } = basicFilterDto;
|
|
164
176
|
|
|
@@ -184,9 +196,15 @@ export class CrudHelperService {
|
|
|
184
196
|
}
|
|
185
197
|
|
|
186
198
|
if (filters) {
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
199
|
+
if (filterCombinator === FilterCombinator.AND) {
|
|
200
|
+
qb.andWhere(new Brackets(whereQb => {
|
|
201
|
+
this.applyFilters(whereQb, filters, entityAlias, qb);
|
|
202
|
+
}));
|
|
203
|
+
} else if (filterCombinator === FilterCombinator.OR) {
|
|
204
|
+
qb.orWhere(new Brackets(whereQb => {
|
|
205
|
+
this.applyFilters(whereQb, filters, entityAlias, qb);
|
|
206
|
+
}));
|
|
207
|
+
}
|
|
190
208
|
}
|
|
191
209
|
|
|
192
210
|
let finalLocale = locale
|
|
@@ -16,6 +16,7 @@ import { User } from '../entities/user.entity';
|
|
|
16
16
|
import { ActiveUserData } from '../interfaces/active-user-data.interface';
|
|
17
17
|
import { iamConfig } from 'src/config/iam.config';
|
|
18
18
|
import { ERROR_MESSAGES } from 'src/constants/error-messages';
|
|
19
|
+
import { UserRepository } from 'src/repository/user.repository';
|
|
19
20
|
|
|
20
21
|
@Injectable()
|
|
21
22
|
export class UserService extends CRUDService<User> {
|
|
@@ -28,8 +29,8 @@ export class UserService extends CRUDService<User> {
|
|
|
28
29
|
readonly crudHelperService: CrudHelperService,
|
|
29
30
|
@InjectEntityManager()
|
|
30
31
|
readonly entityManager: EntityManager,
|
|
31
|
-
@InjectRepository(User, 'default')
|
|
32
|
-
readonly repo:
|
|
32
|
+
// @InjectRepository(User, 'default')
|
|
33
|
+
readonly repo: UserRepository,
|
|
33
34
|
@InjectRepository(RoleMetadata)
|
|
34
35
|
private readonly roleRepository: Repository<RoleMetadata>,
|
|
35
36
|
readonly moduleRef: ModuleRef,
|
|
@@ -21,6 +21,7 @@ import { ActionMetadataService } from './action-metadata.service';
|
|
|
21
21
|
import { SolidIntrospectService } from './solid-introspect.service';
|
|
22
22
|
import { UserViewMetadataService } from './user-view-metadata.service';
|
|
23
23
|
import { ViewMetadataRepository } from 'src/repository/view-metadata.repository';
|
|
24
|
+
import { ModelMetadataHelperService } from 'src/helpers/model-metadata-helper.service';
|
|
24
25
|
|
|
25
26
|
@Injectable()
|
|
26
27
|
export class ViewMetadataService extends CRUDService<ViewMetadata> {
|
|
@@ -42,6 +43,7 @@ export class ViewMetadataService extends CRUDService<ViewMetadata> {
|
|
|
42
43
|
private readonly fieldMetadataRepo: Repository<FieldMetadata>,
|
|
43
44
|
@InjectRepository(ModelMetadata)
|
|
44
45
|
private readonly modelMetadataRepo: Repository<ModelMetadata>,
|
|
46
|
+
private readonly modelMetadataHelperService: ModelMetadataHelperService,
|
|
45
47
|
readonly moduleRef: ModuleRef
|
|
46
48
|
) {
|
|
47
49
|
super(modelMetadataService, moduleMetadataService, configService, fileService, discoveryService, crudHelperService, entityManager, repo, 'viewMetadata', 'solid-core', moduleRef);
|
|
@@ -172,7 +174,7 @@ export class ViewMetadataService extends CRUDService<ViewMetadata> {
|
|
|
172
174
|
}
|
|
173
175
|
|
|
174
176
|
// 5. Create an easy to use map of field metadata, rather than sending an array of fields it becomes easier to use in the frontend.
|
|
175
|
-
const fields = await this.loadFieldHierarchy(modelName);
|
|
177
|
+
const fields = await this.modelMetadataHelperService.loadFieldHierarchy(modelName);
|
|
176
178
|
const fieldsMap = new Map<string, FieldMetadata>();
|
|
177
179
|
for (let i = 0; i < fields.length; i++) {
|
|
178
180
|
const field = fields[i];
|
package/src/solid-core.module.ts
CHANGED
|
@@ -283,6 +283,7 @@ import { Three60WhatsappQueueSubscriberDatabase } from './jobs/database/three60-
|
|
|
283
283
|
import { Three60WhatsappService } from './services/whatsapp/Three60WhatsappService';
|
|
284
284
|
import { ThrottlerStorageRedisService } from '@nest-lab/throttler-storage-redis/src/throttler-storage-redis.service';
|
|
285
285
|
import { isRedisConfigured } from './helpers/environment.helper';
|
|
286
|
+
import { UserRepository } from './repository/user.repository';
|
|
286
287
|
|
|
287
288
|
|
|
288
289
|
@Global()
|
|
@@ -546,6 +547,7 @@ import { isRedisConfigured } from './helpers/environment.helper';
|
|
|
546
547
|
RoleMetadataService,
|
|
547
548
|
PermissionMetadataSeederService,
|
|
548
549
|
UserService,
|
|
550
|
+
UserRepository,
|
|
549
551
|
SettingService,
|
|
550
552
|
ConcatComputedFieldProvider,
|
|
551
553
|
FileStorageProvider,
|
|
@@ -615,6 +617,7 @@ import { isRedisConfigured } from './helpers/environment.helper';
|
|
|
615
617
|
MailFactory,
|
|
616
618
|
ChatterMessageRepository,
|
|
617
619
|
ChatterMessageDetailsRepository,
|
|
620
|
+
|
|
618
621
|
],
|
|
619
622
|
exports: [
|
|
620
623
|
ModuleMetadataService,
|
|
@@ -3,6 +3,9 @@ import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
|
|
|
3
3
|
import { DataSource, EntityMetadata, EntitySubscriberInterface, EventSubscriber, InsertEvent, RemoveEvent, Repository, UpdateEvent } from 'typeorm';
|
|
4
4
|
import { ModelMetadata } from '../entities/model-metadata.entity';
|
|
5
5
|
import { ChatterMessageService } from '../services/chatter-message.service';
|
|
6
|
+
import { lowerFirst } from 'src/helpers/string.helper';
|
|
7
|
+
import { ModelMetadataHelperService } from 'src/helpers/model-metadata-helper.service';
|
|
8
|
+
|
|
6
9
|
@Injectable()
|
|
7
10
|
@EventSubscriber()
|
|
8
11
|
export class AuditSubscriber implements EntitySubscriberInterface {
|
|
@@ -13,6 +16,7 @@ export class AuditSubscriber implements EntitySubscriberInterface {
|
|
|
13
16
|
private readonly chatterMessageService: ChatterMessageService,
|
|
14
17
|
@InjectRepository(ModelMetadata)
|
|
15
18
|
private readonly modelMetadataRepo: Repository<ModelMetadata>,
|
|
19
|
+
private readonly modelMetadataHelperService : ModelMetadataHelperService,
|
|
16
20
|
) {
|
|
17
21
|
this.dataSource.subscribers.push(this);
|
|
18
22
|
}
|
|
@@ -20,7 +24,7 @@ export class AuditSubscriber implements EntitySubscriberInterface {
|
|
|
20
24
|
private async shouldTrackAudit(entity: any, metadata: EntityMetadata): Promise<boolean> {
|
|
21
25
|
const model = await this.modelMetadataRepo.findOne({
|
|
22
26
|
where: {
|
|
23
|
-
|
|
27
|
+
singularName: lowerFirst(metadata.name)
|
|
24
28
|
},
|
|
25
29
|
relations: {
|
|
26
30
|
fields: true,
|
|
@@ -32,7 +36,9 @@ export class AuditSubscriber implements EntitySubscriberInterface {
|
|
|
32
36
|
return false;
|
|
33
37
|
}
|
|
34
38
|
|
|
35
|
-
const
|
|
39
|
+
const modelFields = await this.modelMetadataHelperService.loadFieldHierarchy(model.singularName)
|
|
40
|
+
|
|
41
|
+
const auditFields = modelFields.filter(field =>
|
|
36
42
|
field.enableAuditTracking &&
|
|
37
43
|
!['mediaSingle', 'mediaMultiple', 'computed', 'richText', 'json'].includes(field.type) &&
|
|
38
44
|
!(field.type === 'relation' && field.relationType === 'one-to-many')
|
|
@@ -56,7 +62,7 @@ export class AuditSubscriber implements EntitySubscriberInterface {
|
|
|
56
62
|
|
|
57
63
|
async afterUpdate(event: UpdateEvent<any>) {
|
|
58
64
|
if (await this.shouldTrackAudit(event.entity, event.metadata)) {
|
|
59
|
-
await this.chatterMessageService.postAuditMessageOnUpdate(event.entity, event.metadata, event.databaseEntity);
|
|
65
|
+
await this.chatterMessageService.postAuditMessageOnUpdate(event.entity, event.metadata, event.databaseEntity, event.updatedColumns || []);
|
|
60
66
|
}
|
|
61
67
|
}
|
|
62
68
|
|