@solidstarters/solid-core 1.2.48 → 1.2.49

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 (105) hide show
  1. package/dist/controllers/security-rule.controller.d.ts +41 -0
  2. package/dist/controllers/security-rule.controller.d.ts.map +1 -0
  3. package/dist/controllers/security-rule.controller.js +179 -0
  4. package/dist/controllers/security-rule.controller.js.map +1 -0
  5. package/dist/dtos/create-model-metadata.dto.d.ts +3 -0
  6. package/dist/dtos/create-model-metadata.dto.d.ts.map +1 -1
  7. package/dist/dtos/create-model-metadata.dto.js +18 -1
  8. package/dist/dtos/create-model-metadata.dto.js.map +1 -1
  9. package/dist/dtos/create-security-rule.dto.d.ts +10 -0
  10. package/dist/dtos/create-security-rule.dto.d.ts.map +1 -0
  11. package/dist/dtos/create-security-rule.dto.js +65 -0
  12. package/dist/dtos/create-security-rule.dto.js.map +1 -0
  13. package/dist/dtos/security-rule-config.dto.d.ts +4 -0
  14. package/dist/dtos/security-rule-config.dto.d.ts.map +1 -0
  15. package/dist/dtos/security-rule-config.dto.js +4 -0
  16. package/dist/dtos/security-rule-config.dto.js.map +1 -0
  17. package/dist/dtos/update-security-rule.dto.d.ts +11 -0
  18. package/dist/dtos/update-security-rule.dto.d.ts.map +1 -0
  19. package/dist/dtos/update-security-rule.dto.js +72 -0
  20. package/dist/dtos/update-security-rule.dto.js.map +1 -0
  21. package/dist/entities/model-metadata.entity.d.ts +2 -0
  22. package/dist/entities/model-metadata.entity.d.ts.map +1 -1
  23. package/dist/entities/model-metadata.entity.js +9 -1
  24. package/dist/entities/model-metadata.entity.js.map +1 -1
  25. package/dist/entities/security-rule.entity.d.ts +11 -0
  26. package/dist/entities/security-rule.entity.d.ts.map +1 -0
  27. package/dist/entities/security-rule.entity.js +53 -0
  28. package/dist/entities/security-rule.entity.js.map +1 -0
  29. package/dist/entities/user.entity.d.ts.map +1 -1
  30. package/dist/entities/user.entity.js +2 -1
  31. package/dist/entities/user.entity.js.map +1 -1
  32. package/dist/helpers/solid-registry.d.ts +22 -1
  33. package/dist/helpers/solid-registry.d.ts.map +1 -1
  34. package/dist/helpers/solid-registry.js +29 -0
  35. package/dist/helpers/solid-registry.js.map +1 -1
  36. package/dist/index.d.ts +7 -0
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +7 -0
  39. package/dist/index.js.map +1 -1
  40. package/dist/interfaces.d.ts +2 -0
  41. package/dist/interfaces.d.ts.map +1 -1
  42. package/dist/interfaces.js.map +1 -1
  43. package/dist/repository/security-rule.repository.d.ts +20 -0
  44. package/dist/repository/security-rule.repository.d.ts.map +1 -0
  45. package/dist/repository/security-rule.repository.js +128 -0
  46. package/dist/repository/security-rule.repository.js.map +1 -0
  47. package/dist/repository/solid-base.repository.d.ts +14 -0
  48. package/dist/repository/solid-base.repository.d.ts.map +1 -0
  49. package/dist/repository/solid-base.repository.js +26 -0
  50. package/dist/repository/solid-base.repository.js.map +1 -0
  51. package/dist/seeders/module-metadata-seeder.service.d.ts +5 -1
  52. package/dist/seeders/module-metadata-seeder.service.d.ts.map +1 -1
  53. package/dist/seeders/module-metadata-seeder.service.js +22 -2
  54. package/dist/seeders/module-metadata-seeder.service.js.map +1 -1
  55. package/dist/seeders/seed-data/solid-core-metadata.json +263 -0
  56. package/dist/services/field-metadata.service.d.ts.map +1 -1
  57. package/dist/services/field-metadata.service.js +1 -0
  58. package/dist/services/field-metadata.service.js.map +1 -1
  59. package/dist/services/module-metadata.service.d.ts.map +1 -1
  60. package/dist/services/module-metadata.service.js +1 -0
  61. package/dist/services/module-metadata.service.js.map +1 -1
  62. package/dist/services/request-context.service.d.ts +7 -0
  63. package/dist/services/request-context.service.d.ts.map +1 -0
  64. package/dist/services/request-context.service.js +33 -0
  65. package/dist/services/request-context.service.js.map +1 -0
  66. package/dist/services/security-rule.service.d.ts +27 -0
  67. package/dist/services/security-rule.service.d.ts.map +1 -0
  68. package/dist/services/security-rule.service.js +71 -0
  69. package/dist/services/security-rule.service.js.map +1 -0
  70. package/dist/services/view-metadata.service.d.ts +1 -0
  71. package/dist/services/view-metadata.service.d.ts.map +1 -1
  72. package/dist/services/view-metadata.service.js +22 -7
  73. package/dist/services/view-metadata.service.js.map +1 -1
  74. package/dist/solid-core.module.d.ts.map +1 -1
  75. package/dist/solid-core.module.js +15 -1
  76. package/dist/solid-core.module.js.map +1 -1
  77. package/dist/subscribers/security-rule.subscriber.d.ts +16 -0
  78. package/dist/subscribers/security-rule.subscriber.d.ts.map +1 -0
  79. package/dist/subscribers/security-rule.subscriber.js +123 -0
  80. package/dist/subscribers/security-rule.subscriber.js.map +1 -0
  81. package/dist/tsconfig.tsbuildinfo +1 -1
  82. package/package.json +1 -1
  83. package/src/controllers/security-rule.controller.ts +93 -0
  84. package/src/dtos/create-model-metadata.dto.ts +14 -0
  85. package/src/dtos/create-security-rule.dto.ts +34 -0
  86. package/src/dtos/security-rule-config.dto.ts +5 -0
  87. package/src/dtos/update-security-rule.dto.ts +39 -0
  88. package/src/entities/model-metadata.entity.ts +6 -0
  89. package/src/entities/security-rule.entity.ts +25 -0
  90. package/src/entities/user.entity.ts +2 -1
  91. package/src/helpers/solid-registry.ts +34 -0
  92. package/src/index.ts +9 -0
  93. package/src/interfaces.ts +2 -0
  94. package/src/repository/security-rule.repository.ts +135 -0
  95. package/src/repository/solid-base.repository.ts +45 -0
  96. package/src/seeders/module-metadata-seeder.service.ts +28 -1
  97. package/src/seeders/seed-data/solid-core-metadata.json +264 -0
  98. package/src/seeders/seed-data/solid-core-metadata.json.bkp +6638 -0
  99. package/src/services/field-metadata.service.ts +1 -0
  100. package/src/services/module-metadata.service.ts +1 -0
  101. package/src/services/request-context.service.ts +16 -0
  102. package/src/services/security-rule.service.ts +54 -0
  103. package/src/services/view-metadata.service.ts +26 -7
  104. package/src/solid-core.module.ts +15 -1
  105. package/src/subscribers/security-rule.subscriber.ts +78 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solidstarters/solid-core",
3
- "version": "1.2.48",
3
+ "version": "1.2.49",
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",
@@ -0,0 +1,93 @@
1
+ import { Controller, Post, Body, Param, UploadedFiles, UseInterceptors, Put, Get, Query, Delete, Patch } from '@nestjs/common';
2
+ import { AnyFilesInterceptor } from "@nestjs/platform-express";
3
+ import { ApiBearerAuth, ApiQuery, ApiTags } from '@nestjs/swagger';
4
+ import { SecurityRuleService } from '../services/security-rule.service';
5
+ import { CreateSecurityRuleDto } from '../dtos/create-security-rule.dto';
6
+ import { UpdateSecurityRuleDto } from '../dtos/update-security-rule.dto';
7
+
8
+ enum ShowSoftDeleted {
9
+ INCLUSIVE = "inclusive",
10
+ EXCLUSIVE = "exclusive",
11
+ }
12
+
13
+ @ApiTags('Solid Core')
14
+ @Controller('security-rule')
15
+ export class SecurityRuleController {
16
+ constructor(private readonly service: SecurityRuleService) {}
17
+
18
+ @ApiBearerAuth("jwt")
19
+ @Post()
20
+ @UseInterceptors(AnyFilesInterceptor())
21
+ create(@Body() createDto: CreateSecurityRuleDto, @UploadedFiles() files: Array<Express.Multer.File>) {
22
+ return this.service.create(createDto, files);
23
+ }
24
+
25
+ @ApiBearerAuth("jwt")
26
+ @Post('/bulk')
27
+ @UseInterceptors(AnyFilesInterceptor())
28
+ insertMany(@Body() createDtos: CreateSecurityRuleDto[], @UploadedFiles() filesArray: Express.Multer.File[][] = []) {
29
+ return this.service.insertMany(createDtos, filesArray);
30
+ }
31
+
32
+
33
+ @ApiBearerAuth("jwt")
34
+ @Put(':id')
35
+ @UseInterceptors(AnyFilesInterceptor())
36
+ update(@Param('id') id: number, @Body() updateDto: UpdateSecurityRuleDto, @UploadedFiles() files: Array<Express.Multer.File>) {
37
+ return this.service.update(id, updateDto, files);
38
+ }
39
+
40
+ @ApiBearerAuth("jwt")
41
+ @Patch(':id')
42
+ @UseInterceptors(AnyFilesInterceptor())
43
+ partialUpdate(@Param('id') id: number, @Body() updateDto: UpdateSecurityRuleDto, @UploadedFiles() files: Array<Express.Multer.File>) {
44
+ return this.service.update(id, updateDto, files, true);
45
+ }
46
+
47
+ @ApiBearerAuth("jwt")
48
+ @Post('/bulk-recover')
49
+ async recoverMany(@Body() ids: number[]) {
50
+ return this.service.recoverMany(ids);
51
+ }
52
+
53
+ @ApiBearerAuth("jwt")
54
+ @Get('/recover/:id')
55
+ async recover(@Param('id') id: number) {
56
+ return this.service.recover(id);
57
+ }
58
+
59
+ @ApiBearerAuth("jwt")
60
+ @ApiQuery({ name: 'showSoftDeleted', required: false, enum: ShowSoftDeleted })
61
+ @ApiQuery({ name: 'limit', required: false, type: Number })
62
+ @ApiQuery({ name: 'offset', required: false, type: Number })
63
+ @ApiQuery({ name: 'fields', required: false, type: Array })
64
+ @ApiQuery({ name: 'sort', required: false, type: Array })
65
+ @ApiQuery({ name: 'groupBy', required: false, type: Array })
66
+ @ApiQuery({ name: 'populate', required: false, type: Array })
67
+ @ApiQuery({ name: 'populateMedia', required: false, type: Array })
68
+ @ApiQuery({ name: 'filters', required: false, type: Array })
69
+ @Get()
70
+ async findMany(@Query() query: any) {
71
+ return this.service.find(query);
72
+ }
73
+
74
+ @ApiBearerAuth("jwt")
75
+ @Get(':id')
76
+ async findOne(@Param('id') id: string, @Query() query: any) {
77
+ return this.service.findOne(+id, query);
78
+ }
79
+
80
+ @ApiBearerAuth("jwt")
81
+ @Delete('/bulk')
82
+ async deleteMany(@Body() ids: number[]) {
83
+ return this.service.deleteMany(ids);
84
+ }
85
+
86
+ @ApiBearerAuth("jwt")
87
+ @Delete(':id')
88
+ async delete(@Param('id') id: number) {
89
+ return this.service.delete(id);
90
+ }
91
+
92
+
93
+ }
@@ -94,4 +94,18 @@ export class CreateModelMetadataDto {
94
94
  @ApiProperty({ description: 'System models are not included in the code generation, the assumption being that system models have manually written code.', })
95
95
  @IsBoolean()
96
96
  isSystem: boolean;
97
+
98
+ @ApiProperty({ description: 'Child models are not included in the code generation, the assumption being that child models have manually written code.', })
99
+ @IsBoolean()
100
+ isChild: boolean;
101
+
102
+ @ApiProperty({ description: 'Parent model id' })
103
+ @IsInt()
104
+ @IsOptional()
105
+ parentModelId: number;
106
+
107
+ @ApiProperty({ description: 'Parent model user key' })
108
+ @IsString()
109
+ @IsOptional()
110
+ parentModelUserKey: string;
97
111
  }
@@ -0,0 +1,34 @@
1
+ import { ApiProperty } from '@nestjs/swagger';
2
+ import { IsString } from 'class-validator';
3
+ import { IsNotEmpty, IsInt, IsOptional, IsJSON } from 'class-validator';
4
+
5
+ export class CreateSecurityRuleDto {
6
+ @IsNotEmpty()
7
+ @IsString()
8
+ @ApiProperty()
9
+ name: string;
10
+ @IsNotEmpty()
11
+ @IsString()
12
+ @ApiProperty()
13
+ description: string;
14
+ @IsOptional()
15
+ @IsInt()
16
+ @ApiProperty()
17
+ roleId: number;
18
+ @IsString()
19
+ @IsOptional()
20
+ @ApiProperty()
21
+ roleUserKey: string;
22
+ @IsOptional()
23
+ @IsInt()
24
+ @ApiProperty()
25
+ modelMetadataId: number;
26
+ @IsString()
27
+ @IsOptional()
28
+ @ApiProperty()
29
+ modelMetadataUserKey: string;
30
+ @IsNotEmpty()
31
+ @IsJSON()
32
+ @ApiProperty()
33
+ securityRuleConfig: any;
34
+ }
@@ -0,0 +1,5 @@
1
+ import { BasicFilterDto } from "./basic-filters.dto";
2
+
3
+ export interface SecurityRuleConfig {
4
+ filters: Record<string, any>;
5
+ }
@@ -0,0 +1,39 @@
1
+ import { IsInt,IsOptional, IsString, IsNotEmpty, IsJSON } from 'class-validator';
2
+ import { ApiProperty } from '@nestjs/swagger';
3
+
4
+ export class UpdateSecurityRuleDto {
5
+ @IsOptional()
6
+ @IsInt()
7
+ id: number;
8
+ @IsNotEmpty()
9
+ @IsOptional()
10
+ @IsString()
11
+ @ApiProperty()
12
+ name: string;
13
+ @IsNotEmpty()
14
+ @IsOptional()
15
+ @IsString()
16
+ @ApiProperty()
17
+ description: string;
18
+ @IsOptional()
19
+ @IsInt()
20
+ @ApiProperty()
21
+ roleId: number;
22
+ @IsString()
23
+ @IsOptional()
24
+ @ApiProperty()
25
+ roleUserKey: string;
26
+ @IsOptional()
27
+ @IsInt()
28
+ @ApiProperty()
29
+ modelMetadataId: number;
30
+ @IsString()
31
+ @IsOptional()
32
+ @ApiProperty()
33
+ modelMetadataUserKey: string;
34
+ @IsNotEmpty()
35
+ @IsOptional()
36
+ @IsJSON()
37
+ @ApiProperty()
38
+ securityRuleConfig: any;
39
+ }
@@ -56,4 +56,10 @@ export class ModelMetadata extends CommonEntity {
56
56
 
57
57
  @Column({ default: false })
58
58
  isSystem: boolean;
59
+
60
+ @Column({ default: false })
61
+ isChild: boolean;
62
+
63
+ @ManyToOne(() => ModelMetadata, { onDelete: 'CASCADE' })
64
+ parentModel: ModelMetadata;
59
65
  }
@@ -0,0 +1,25 @@
1
+ import { CommonEntity } from 'src/entities/common.entity';
2
+ import { ModelMetadata } from 'src/entities/model-metadata.entity';
3
+ import { RoleMetadata } from 'src/entities/role-metadata.entity';
4
+ import { Column, Entity, Index, JoinColumn, ManyToOne } from 'typeorm';
5
+
6
+ @Entity("ss_security_rule")
7
+ export class SecurityRule extends CommonEntity {
8
+ @Index({ unique: true })
9
+ @Column({ type: "varchar" })
10
+ name: string;
11
+ @Index({ unique: true })
12
+ @Column({ type: "varchar" })
13
+ description: string;
14
+ @Index()
15
+ @ManyToOne(() => RoleMetadata, { onDelete: "CASCADE", nullable: false })
16
+ @JoinColumn()
17
+ role: RoleMetadata;
18
+ @Index()
19
+ @ManyToOne(() => ModelMetadata, { onDelete: "CASCADE", nullable: false })
20
+ @JoinColumn()
21
+ modelMetadata: ModelMetadata;
22
+ @Column({ type: "text" })
23
+ securityRuleConfig: any;
24
+
25
+ }
@@ -1,9 +1,10 @@
1
1
  import { CommonEntity } from "src/entities/common.entity"
2
- import { Entity, Column, Index, JoinTable, ManyToMany, OneToMany } from "typeorm";
2
+ import { Entity, Column, Index, JoinTable, ManyToMany, OneToMany, TableInheritance } from "typeorm";
3
3
  import { RoleMetadata } from 'src/entities/role-metadata.entity';
4
4
  import { UserViewMetadata } from 'src/entities/user-view-metadata.entity'
5
5
 
6
6
  @Entity("ss_user")
7
+ @TableInheritance({ column: { type: "varchar", name: "type", default: "User" } })
7
8
  export class User extends CommonEntity {
8
9
  @Column({ type: "varchar", nullable: true })
9
10
  fullName: string;
@@ -1,6 +1,7 @@
1
1
  import { Injectable } from '@nestjs/common';
2
2
  import { InstanceWrapper } from '@nestjs/core/injector/instance-wrapper';
3
3
  import { ISelectionProvider, ISelectionProviderContext } from "../interfaces";
4
+ import { SecurityRule } from 'src/entities/security-rule.entity';
4
5
 
5
6
  type ControllerMetadata = {
6
7
  name: string;
@@ -14,6 +15,23 @@ export enum RESERVED_SOLID_KEYWORDS {
14
15
  dataSource = "dataSource",
15
16
  repository = "repository",
16
17
  entityManager = "entityManager",
18
+ actionMetadata = "actionMetadata",
19
+ emailAttachment = "emailAttachment",
20
+ emailTemplate = "emailTemplate",
21
+ listOfValues = "listOfValues",
22
+ mediaStorageProvider = "mediaStorageProvider",
23
+ media = "media",
24
+ menuItemMetadata = "menuItemMetadata",
25
+ mqMessageQueue = "mqMessageQueue",
26
+ mqMessage = "mqMessage",
27
+ permissionMetadata = "permissionMetadata",
28
+ roleMetadata = "roleMetadata",
29
+ securityRule = "securityRule",
30
+ setting = "setting",
31
+ smsTemplate = "smsTemplate",
32
+ userPasswordHistory = "userPasswordHistory",
33
+ userMetadata = "userMetadata",
34
+ user = "user",
17
35
  }
18
36
 
19
37
  @Injectable()
@@ -24,6 +42,7 @@ export class SolidRegistry {
24
42
  private solidDatabaseModules: Set<InstanceWrapper> = new Set();
25
43
  private controllers: Set<ControllerMetadata> = new Set();
26
44
  private modules : Set<InstanceWrapper> = new Set();
45
+ private securityRules: SecurityRule[] = [];
27
46
 
28
47
  registerController(name: string, methodNames: string[]): void {
29
48
  this.controllers.add({ name: name, methods: methodNames });
@@ -92,4 +111,19 @@ export class SolidRegistry {
92
111
  const module = this.getModules().filter((module) => module.name === name).pop();
93
112
  return module
94
113
  }
114
+
115
+ registerSecurityRules(securityRules: SecurityRule[]) {
116
+ this.securityRules = securityRules;
117
+ }
118
+
119
+ getSecurityRules(modelSingularName:string, roleNames: string[] = []): SecurityRule[] {
120
+ // If no role is provided, return all security rules for the model
121
+ if (roleNames.length === 0) {
122
+ return this.securityRules.filter((rule) => rule.modelMetadata.singularName === modelSingularName);
123
+ }
124
+ // If roles are provided, filter the security rules by model and roles
125
+ return this.securityRules.filter((rule) => {
126
+ return rule.modelMetadata.singularName === modelSingularName && roleNames.includes(rule.role.name);
127
+ });
128
+ }
95
129
  }
package/src/index.ts CHANGED
@@ -78,6 +78,8 @@ export * from './dtos/update-user.dto'
78
78
  export * from './dtos/update-view-metadata.dto'
79
79
  export * from './dtos/create-setting.dto'
80
80
  export * from './dtos/update-setting.dto'
81
+ export * from './dtos/create-security-rule.dto'
82
+ export * from './dtos/update-security-rule.dto'
81
83
 
82
84
 
83
85
  export * from './entities/action-metadata.entity'
@@ -101,6 +103,7 @@ export * from './entities/user.entity'
101
103
  export * from './entities/view-metadata.entity'
102
104
  export * from './entities/setting.entity'
103
105
  export * from './entities/user-view-metadata.entity'
106
+ export * from './entities/security-rule.entity'
104
107
 
105
108
  export * from './enums/auth-type.enum'
106
109
 
@@ -214,6 +217,12 @@ export * from './services/user.service'
214
217
  export * from './services/view-metadata.service'
215
218
  export * from './services/whatsapp/Msg91WhatsappService' //rename
216
219
  export * from './services/setting.service'
220
+ export * from './services/security-rule.service'
221
+ export * from './services/request-context.service'
222
+
223
+ // Repositories
224
+ export * from './repository/solid-base.repository'
225
+ export * from './repository/security-rule.repository'
217
226
 
218
227
 
219
228
  //softDeleteAwareEventSubscriber.subscriber.ts
package/src/interfaces.ts CHANGED
@@ -10,6 +10,7 @@ import { CreateRoleMetadataDto } from './dtos/create-role-metadata.dto';
10
10
  import { CreateViewMetadataDto } from './dtos/create-view-metadata.dto';
11
11
  import { FieldMetadata } from './entities/field-metadata.entity';
12
12
  import { Media } from './entities/media.entity';
13
+ import { CreateSecurityRuleDto } from './dtos/create-security-rule.dto';
13
14
 
14
15
  export interface FieldCrudManager {
15
16
  // fieldMetadata: FieldMetadata;
@@ -46,6 +47,7 @@ export interface ModuleMetadataConfiguration {
46
47
  emailTemplates?: CreateEmailTemplateDto[],
47
48
  smsTemplates?: CreateSmsTemplateDto[],
48
49
  mediaStorageProviders?: CreateMediaStorageProviderMetadataDto[]
50
+ securityRules?: CreateSecurityRuleDto[],
49
51
  }
50
52
 
51
53
  export interface CodeGenerationOptions {
@@ -0,0 +1,135 @@
1
+ import { Injectable, Logger } from '@nestjs/common';
2
+ import { CreateSecurityRuleDto } from 'src/dtos/create-security-rule.dto';
3
+ import { SecurityRuleConfig } from 'src/dtos/security-rule-config.dto';
4
+ import { UpdateSecurityRuleDto } from 'src/dtos/update-security-rule.dto';
5
+ import { CommonEntity } from 'src/entities/common.entity';
6
+ import { ModelMetadata } from 'src/entities/model-metadata.entity';
7
+ import { RoleMetadata } from 'src/entities/role-metadata.entity';
8
+ import { SecurityRule } from 'src/entities/security-rule.entity';
9
+ import { SolidRegistry } from 'src/helpers/solid-registry';
10
+ import { ActiveUserData } from 'src/interfaces/active-user-data.interface';
11
+ import { CrudHelperService } from 'src/services/crud-helper.service';
12
+ import { DataSource, Repository, SelectQueryBuilder } from 'typeorm';
13
+
14
+ @Injectable()
15
+ export class SecurityRuleRepository extends Repository<SecurityRule> {
16
+ private readonly logger = new Logger(SecurityRuleRepository.name);
17
+ constructor(
18
+ private dataSource: DataSource,
19
+ private readonly solidRegistry: SolidRegistry,
20
+ private readonly crudHelperService: CrudHelperService,
21
+ ) {
22
+ super(SecurityRule, dataSource.createEntityManager());
23
+ }
24
+
25
+ applySecurityRules<T extends CommonEntity>(qb: SelectQueryBuilder<T>, modelSingularName: string, activeUser: ActiveUserData,): SelectQueryBuilder<T> {
26
+ // Fetch the security rules for the model and roles
27
+ const securityRules = this.solidRegistry.getSecurityRules(modelSingularName, activeUser.roles);
28
+
29
+ // Loop through the security rules and add only rules that are json parseable and have a rule
30
+ securityRules.forEach((rule: SecurityRule) => {
31
+ try {
32
+ // Parse the security rule and call the buildFilter method to build the query from the security rule
33
+ const parsedRule = JSON.parse(this.resolveSecurityRuleConfig(rule.securityRuleConfig, activeUser)) as SecurityRuleConfig;
34
+ if (parsedRule && parsedRule.filters) {
35
+ this.crudHelperService.buildFilterQuery(qb, parsedRule, qb.alias);
36
+ }
37
+ } catch (error) {
38
+ this.logger.warn(`Error parsing security rule: ${rule.securityRuleConfig}`, error);
39
+ }
40
+ });
41
+
42
+ return qb;
43
+ }
44
+
45
+
46
+ private resolveSecurityRuleConfig(configString: string, activeUser: ActiveUserData) {
47
+ return configString.replace('$activeUserId', activeUser.sub.toString());
48
+ }
49
+
50
+ async toDto(securityRule: SecurityRule): Promise<UpdateSecurityRuleDto> {
51
+ // load the role and model relations for the security rule
52
+ let populatedSecurityRule: SecurityRule = securityRule;
53
+ // If the security rule does not have the role and model relations loaded, load them
54
+ if (!securityRule.role || !securityRule.modelMetadata) {
55
+ populatedSecurityRule = await this.findOne({
56
+ where: {
57
+ id: securityRule.id,
58
+ },
59
+ relations: {
60
+ role: true,
61
+ modelMetadata: true,
62
+ },
63
+ });
64
+ }
65
+
66
+ return {
67
+ id: populatedSecurityRule.id,
68
+ name: populatedSecurityRule.name,
69
+ description: populatedSecurityRule.description,
70
+ roleId: populatedSecurityRule.role.id,
71
+ roleUserKey: populatedSecurityRule.role.name,
72
+ modelMetadataId: populatedSecurityRule.modelMetadata.id,
73
+ modelMetadataUserKey: populatedSecurityRule.modelMetadata.singularName,
74
+ securityRuleConfig: populatedSecurityRule.securityRuleConfig,
75
+ };
76
+ }
77
+
78
+ async upsertWithDto(createDto: CreateSecurityRuleDto) {
79
+ // Populate the role from roleId or roleUserKey
80
+ const roleRepository = this.dataSource.getRepository(RoleMetadata);
81
+ if (!createDto.roleId) {
82
+ const role = await roleRepository.findOne({
83
+ where: {
84
+ id: createDto.roleId,
85
+ },
86
+ });
87
+ createDto['role'] = role;
88
+ }
89
+
90
+ if (createDto.roleUserKey) {
91
+ const role = await roleRepository.findOne({
92
+ where: {
93
+ name: createDto.roleUserKey,
94
+ },
95
+ });
96
+ createDto['role'] = role;
97
+ }
98
+
99
+ // Populate the model from modelMetadataId or modelMetadataUserKey
100
+ const modelMetadataRepository = this.dataSource.getRepository(ModelMetadata);
101
+ if (!createDto.modelMetadataId) {
102
+ const modelMetadata = await modelMetadataRepository.findOne({
103
+ where: {
104
+ id: createDto.modelMetadataId,
105
+ },
106
+ });
107
+ createDto['modelMetadata'] = modelMetadata;
108
+ }
109
+ if (createDto.modelMetadataUserKey) {
110
+ const modelMetadata = await modelMetadataRepository.findOne({
111
+ where: {
112
+ singularName: createDto.modelMetadataUserKey,
113
+ },
114
+ });
115
+ createDto['modelMetadata'] = modelMetadata;
116
+ }
117
+
118
+ // First check if module already exists using name
119
+ const existingSecurityRule = await this.findOne({
120
+ where: {
121
+ name: createDto.name,
122
+ },
123
+ });
124
+
125
+ if (existingSecurityRule) {
126
+ const updatedSecurityRule = this.merge(existingSecurityRule, createDto);
127
+ return this.save(updatedSecurityRule);
128
+ }
129
+ else {
130
+ const securityRule = this.create(createDto);
131
+ return this.save(securityRule);
132
+ }
133
+ }
134
+
135
+ }
@@ -0,0 +1,45 @@
1
+ import { camelize } from '@angular-devkit/core/src/utils/strings';
2
+ import { Logger } from '@nestjs/common';
3
+ import { CommonEntity } from 'src/entities/common.entity';
4
+ import { ActiveUserData } from 'src/interfaces/active-user-data.interface';
5
+ import { RequestContextService } from 'src/services/request-context.service';
6
+ import {
7
+ DataSource,
8
+ EntityTarget,
9
+ QueryRunner,
10
+ Repository,
11
+ SelectQueryBuilder
12
+ } from 'typeorm';
13
+ import { SecurityRuleRepository } from './security-rule.repository';
14
+
15
+ export class SolidBaseRepository<T extends CommonEntity> extends Repository<T> {
16
+ protected readonly logger: Logger;
17
+
18
+ constructor(
19
+ entity: EntityTarget<T>,
20
+ dataSource: DataSource,
21
+ protected readonly requestContextService: RequestContextService,
22
+ protected readonly securityRuleRepository: SecurityRuleRepository
23
+ ) {
24
+ super(entity, dataSource.createEntityManager());
25
+ this.logger = new Logger(this.constructor.name);
26
+ }
27
+
28
+ modelSingularName(): string {
29
+ return camelize(this.metadata.name);
30
+ }
31
+
32
+ createQueryBuilder(alias?: string, queryRunner?: QueryRunner): SelectQueryBuilder<T> {
33
+ const activeUserOrUndefined = this.requestContextService.getActiveUser();
34
+ const qb = super.createQueryBuilder(alias, queryRunner);
35
+ if (!activeUserOrUndefined) return qb;
36
+
37
+ return this.securityRuleRepository.applySecurityRules(
38
+ qb,
39
+ this.modelSingularName(),
40
+ activeUserOrUndefined as ActiveUserData
41
+ );
42
+ }
43
+
44
+
45
+ }
@@ -32,6 +32,8 @@ import commonConfig from 'src/config/common.config';
32
32
  import { CreateSettingDto } from 'src/dtos/create-setting.dto';
33
33
  import { SettingService } from 'src/services/setting.service';
34
34
  import { Setting } from 'src/entities/setting.entity';
35
+ import { CreateSecurityRuleDto } from 'src/dtos/create-security-rule.dto';
36
+ import { SecurityRuleRepository } from 'src/repository/security-rule.repository';
35
37
 
36
38
  @Injectable()
37
39
  export class ModuleMetadataSeederService {
@@ -62,6 +64,7 @@ export class ModuleMetadataSeederService {
62
64
  private readonly service: SettingService,
63
65
  @InjectRepository(Setting, 'default')
64
66
  readonly settingsRepo: Repository<Setting>,
67
+ readonly securityRuleRepo: SecurityRuleRepository,
65
68
  ) { }
66
69
 
67
70
  async seed() {
@@ -190,11 +193,17 @@ export class ModuleMetadataSeederService {
190
193
  await this.seedSmsTemplates(smsTemplates);
191
194
  this.logger.debug(`[End] Processing sms templates for ${moduleMetadata.name}`);
192
195
 
193
- // Sms templates
196
+ // Settings
194
197
  this.logger.debug(`[Start] Processing settings for ${moduleMetadata.name}`);
195
198
  await this.seedSettings(settingsSeederData);
196
199
  this.logger.debug(`[End] Processing settings for ${moduleMetadata.name}`);
197
200
 
201
+ // Security rules
202
+ this.logger.debug(`[Start] Processing security rules for ${moduleMetadata.name}`);
203
+ const securityRules: CreateSecurityRuleDto[] = overallMetadata.securityRules;
204
+ await this.seedSecurityRules(securityRules);
205
+ this.logger.debug(`[End] Processing security rules for ${moduleMetadata.name}`);
206
+
198
207
  this.logger.debug(`[End] module seed data: ${overallMetadata}`);
199
208
 
200
209
  }
@@ -449,6 +458,13 @@ export class ModuleMetadataSeederService {
449
458
  // const fieldsMetadata = modelMetdata.fields;
450
459
  // delete modelMetdata['fields'];
451
460
  const { fields: fieldsMetadata, ...modelMetaDataWithoutFields } = modelMetadata;
461
+
462
+ // Load and set the parent model if it exists.
463
+ if (modelMetadata.isChild && modelMetadata.parentModelUserKey) {
464
+ const parentModel = await this.modelMetadataService.findOneByUserKey(modelMetadata.parentModelUserKey);
465
+ modelMetaDataWithoutFields['parentModel'] = parentModel;
466
+ }
467
+
452
468
  await this.modelMetadataService.upsert(modelMetaDataWithoutFields);
453
469
  const model = await this.modelMetadataService.findOneBySingularName(modelMetadata.singularName)
454
470
 
@@ -486,4 +502,15 @@ export class ModuleMetadataSeederService {
486
502
  this.service.create(createDto);
487
503
  }
488
504
  }
505
+
506
+ async seedSecurityRules(rulesDto: CreateSecurityRuleDto[]) {
507
+ if (!rulesDto || rulesDto.length === 0) {
508
+ this.logger.debug(`No security rules found to seed`);
509
+ return;
510
+ }
511
+ for (const dto of rulesDto) {
512
+ await this.securityRuleRepo.upsertWithDto({...dto, securityRuleConfig: JSON.stringify(dto.securityRuleConfig)});
513
+ }
514
+ }
515
+
489
516
  }