rez_core 1.0.79 → 1.0.82

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 (26) hide show
  1. package/dist/module/meta/service/entity-service-impl.service.d.ts +3 -1
  2. package/dist/module/meta/service/entity-service-impl.service.js +12 -0
  3. package/dist/module/meta/service/entity-service-impl.service.js.map +1 -1
  4. package/dist/module/meta/service/entity-validation.service.d.ts +5 -3
  5. package/dist/module/meta/service/entity-validation.service.js +26 -16
  6. package/dist/module/meta/service/entity-validation.service.js.map +1 -1
  7. package/dist/module/meta/service/media-data.service.d.ts +1 -1
  8. package/dist/module/user/repository/role.repository.d.ts +4 -1
  9. package/dist/module/user/repository/role.repository.js +8 -3
  10. package/dist/module/user/repository/role.repository.js.map +1 -1
  11. package/dist/module/user/repository/user.repository.d.ts +2 -2
  12. package/dist/module/user/repository/user.repository.js +16 -10
  13. package/dist/module/user/repository/user.repository.js.map +1 -1
  14. package/dist/module/user/service/role.service.js +2 -2
  15. package/dist/module/user/service/role.service.js.map +1 -1
  16. package/dist/module/user/service/user.service.d.ts +2 -2
  17. package/dist/module/user/service/user.service.js +22 -14
  18. package/dist/module/user/service/user.service.js.map +1 -1
  19. package/dist/tsconfig.build.tsbuildinfo +1 -1
  20. package/package.json +1 -1
  21. package/src/module/meta/service/entity-service-impl.service.ts +15 -1
  22. package/src/module/meta/service/entity-validation.service.ts +34 -18
  23. package/src/module/user/repository/role.repository.ts +15 -5
  24. package/src/module/user/repository/user.repository.ts +22 -13
  25. package/src/module/user/service/role.service.ts +2 -2
  26. package/src/module/user/service/user.service.ts +46 -16
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rez_core",
3
- "version": "1.0.79",
3
+ "version": "1.0.82",
4
4
  "description": "",
5
5
  "author": "",
6
6
  "private": false,
@@ -16,6 +16,7 @@ import { ExcelsheetData } from '../../../utils/dto/excelsheet-data.dto';
16
16
  import { EntityTableService } from './entity-table.service';
17
17
  import { EntityTableColumnService } from './entity-table-column.service';
18
18
  import { ENTITYTYPE_ENTITYMASTER } from '../../../constant/global.constant';
19
+ import { EntityValidationService } from './entity-validation.service';
19
20
 
20
21
  @Injectable()
21
22
  export class EntityServiceImpl implements EntityService<BaseEntity> {
@@ -26,12 +27,15 @@ export class EntityServiceImpl implements EntityService<BaseEntity> {
26
27
  @Inject() protected readonly reflectionHelper: ReflectionHelper;
27
28
  @Inject() protected readonly entityListService: EntityListService;
28
29
  @Inject() protected readonly loggingService: LoggingService;
30
+ @Inject()
31
+ protected readonly entityValidationService: EntityValidationService;
32
+
29
33
 
30
34
  async createEntity(
31
35
  entityData: BaseEntity,
32
36
  loggedInUser: UserData | null,
33
37
  manager?: EntityManager,
34
- ): Promise<BaseEntity> {
38
+ ){
35
39
  if (!entityData.entity_type) {
36
40
  throw new BadRequestException(`EntityType is missing`);
37
41
  }
@@ -39,6 +43,16 @@ export class EntityServiceImpl implements EntityService<BaseEntity> {
39
43
  entityData.entity_type,
40
44
  );
41
45
 
46
+ const validationErrors = await this.entityValidationService.validateEntityData(entityData,entityMaster);
47
+ if (validationErrors.length > 0) {
48
+
49
+ return {
50
+ success: false,
51
+ errors: validationErrors,
52
+ };
53
+
54
+ }
55
+
42
56
  const repo = manager
43
57
  ? manager.getRepository(entityMaster.entity_data_class) // <-- Use transaction-safe repo
44
58
  : this.reflectionHelper.getRepoService(entityMaster.entity_data_class);
@@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common';
2
2
  import { AttributeMasterService } from 'src/module/meta/service/attribute-master.service';
3
3
  import { AttributeMaster } from '../entity/attribute-master.entity';
4
4
  import { ReflectionHelper } from 'src/utils/service/reflection-helper.service';
5
+ import { DataSource } from 'typeorm';
5
6
 
6
7
  interface ValidationError {
7
8
  field: string;
@@ -12,7 +13,8 @@ interface ValidationError {
12
13
  export class EntityValidationService {
13
14
  constructor(
14
15
  private readonly attributeMasterService: AttributeMasterService,
15
- private readonly reflectionHelper: ReflectionHelper
16
+ private readonly reflectionHelper: ReflectionHelper,
17
+ private dataSource: DataSource
16
18
  ) {}
17
19
 
18
20
  /**
@@ -27,11 +29,11 @@ export class EntityValidationService {
27
29
  attributeData
28
30
  .filter(attr => attr.required)
29
31
  .forEach(attr => {
30
- const value = entityData[attr.code];
32
+ const value = entityData[attr.attribute_key];
31
33
  if (!this.hasValidValue(value)) {
32
34
  errors.push({
33
- field: attr.code,
34
- message: `Field "${attr.code}" is required.`,
35
+ field: attr.name,
36
+ message: `Field ${attr.name} is required.`,
35
37
  });
36
38
  }
37
39
  });
@@ -45,24 +47,37 @@ export class EntityValidationService {
45
47
  async validateUniqueFields(
46
48
  entityData: Record<string, any>,
47
49
  attributeData: AttributeMaster[],
48
- entityType: string
50
+ entityType: string,
51
+ db_table_name: string
49
52
  ): Promise<ValidationError[]> {
50
53
  const errors: ValidationError[] = [];
51
54
 
52
- const repo = this.reflectionHelper.getRepoService(entityData.entity_type);
53
-
54
- if (!repo) {
55
- throw new Error(`Repository service not found for entityType: ${entityType}`);
56
- }
57
-
58
55
  for (const attr of attributeData.filter(a => a.is_unique)) {
59
- const value = entityData[attr.code];
56
+ const value = entityData[attr.attribute_key];
57
+
60
58
  if (this.hasValidValue(value)) {
61
- const existing = await repo.findOne({ where: { [attr.code]: value } });
59
+ let qb = this.dataSource
60
+ .createQueryBuilder()
61
+ .select('*')
62
+ .from(db_table_name, db_table_name)
63
+ .where(`${db_table_name}.${attr.attribute_key} = :value`, { value });
64
+
65
+ // Add AND condition for organization_id if present
66
+ const orgId = entityData.organization_id;
67
+
68
+ if (orgId !== undefined && orgId !== null) {
69
+ qb = qb.andWhere(`${db_table_name}.organization_id = :organization_id`, {
70
+ organization_id: orgId,
71
+ });
72
+ }
73
+
74
+
75
+ const existing = await qb.limit(1).getRawOne();
76
+
62
77
  if (existing) {
63
78
  errors.push({
64
- field: attr.code,
65
- message: `Field "${attr.code}" must be unique. Value "${value}" already exists.`,
79
+ field: attr.name,
80
+ message: `Field ${attr.name} must be unique. Value ${value} already exists.`,
66
81
  });
67
82
  }
68
83
  }
@@ -71,17 +86,18 @@ export class EntityValidationService {
71
86
  return errors;
72
87
  }
73
88
 
74
-
89
+
75
90
  /**
76
91
  * Validates both required and unique fields for a given entity type.
77
92
  */
78
93
  async validateEntityData(
79
- entityData: Record<string, any>
94
+ entityData: Record<string, any>,
95
+ entityMaster
80
96
  ): Promise<ValidationError[]> {
81
97
  const attributes = await this.attributeMasterService.findAttributesByMappedEntityType(entityData.entity_type);
82
98
 
83
99
  const requiredErrors = this.validateRequiredFields(entityData, attributes);
84
- const uniqueErrors = await this.validateUniqueFields(entityData, attributes, entityData.entity_type);
100
+ const uniqueErrors = await this.validateUniqueFields(entityData, attributes, entityData.entity_type,entityMaster.db_table_name);
85
101
 
86
102
  return [...requiredErrors, ...uniqueErrors];
87
103
  }
@@ -17,16 +17,26 @@ export class RoleRepository {
17
17
  }
18
18
 
19
19
 
20
- public async isRoleNameExists(name: string, excludeRoleId?: number): Promise<boolean> {
20
+ public async isRoleNameExists(
21
+ name: string,
22
+ options?: { excludeRoleId?: number; organization_id?: number }
23
+ ): Promise<boolean> {
21
24
  const query = this.roleRepo
22
25
  .createQueryBuilder('role')
23
26
  .where('role.name = :name', { name });
24
-
25
- if (excludeRoleId) {
26
- query.andWhere('role.id != :excludeRoleId', { excludeRoleId });
27
+
28
+ if (options?.excludeRoleId) {
29
+ query.andWhere('role.id != :excludeRoleId', { excludeRoleId: options.excludeRoleId });
27
30
  }
28
-
31
+
32
+ if (options?.organization_id !== undefined) {
33
+ query.andWhere('role.organization_id = :organization_id', {
34
+ organization_id: options.organization_id,
35
+ });
36
+ }
37
+
29
38
  const existingRole = await query.getOne();
30
39
  return !!existingRole;
31
40
  }
41
+
32
42
  }
@@ -9,23 +9,32 @@ export class UserRepository {
9
9
  @InjectRepository(UserData) private userRepository: Repository<UserData>,
10
10
  ) {}
11
11
 
12
- async findByEmailId(email: string): Promise<UserData | null> {
13
- if (email) {
14
- return this.userRepository.findOne({ where: { email_id: email } });
15
- }
16
- return null;
17
- }
18
-
19
- async findById(userId: number): Promise<UserData | null> {
12
+ async findById(userId: number ): Promise<UserData | null> {
20
13
  return this.userRepository.findOne({ where: { id: userId } });
21
14
  }
22
-
23
- async findByMobile(mobile: string): Promise<UserData | null> {
24
- if (mobile) {
25
- return this.userRepository.findOne({ where: { mobile: mobile } });
15
+ async findByEmailId(email: string, organization_id?: number): Promise<UserData | null> {
16
+ if (!email) return null;
17
+
18
+ const where: any = { email_id: email };
19
+ if (organization_id !== undefined) {
20
+ where.organization_id = organization_id;
21
+ }
22
+
23
+ return this.userRepository.findOne({ where });
24
+ }
25
+
26
+ async findByMobile(mobile: string, organization_id?: number): Promise<UserData | null> {
27
+ if (!mobile) return null;
28
+
29
+ const where: any = { mobile: mobile };
30
+ if (organization_id !== undefined) {
31
+ where.organization_id = organization_id;
26
32
  }
27
- return null;
33
+
34
+ return this.userRepository.findOne({ where });
28
35
  }
36
+
37
+
29
38
 
30
39
  async saveUser(user: UserData): Promise<UserData> {
31
40
  return this.userRepository.save(user);
@@ -27,7 +27,7 @@ export class RoleService extends EntityServiceImpl {
27
27
  ): Promise<BaseEntity> {
28
28
  let role = entityData as Role;
29
29
 
30
- if (await this.roleRepository.isRoleNameExists(role.name)) {
30
+ if (await this.roleRepository.isRoleNameExists(role.name,{organization_id:entityData.organization_id})) {
31
31
  throw new BadRequestException('Role name already exists.');
32
32
  }
33
33
 
@@ -98,7 +98,7 @@ export class RoleService extends EntityServiceImpl {
98
98
  }
99
99
 
100
100
  if (
101
- await this.roleRepository.isRoleNameExists(entityData.name, entityData.id)
101
+ await this.roleRepository.isRoleNameExists(entityData.name, {excludeRoleId:entityData.id})
102
102
  ) {
103
103
  throw new BadRequestException('Role name already exists.');
104
104
  }
@@ -39,12 +39,16 @@ export class UserService extends EntityServiceImpl {
39
39
  let userData = entityData as CreateUserDto;
40
40
  let existingUser = await this.userRepository.findByEmailId(
41
41
  userData.email_id,
42
+ userData.organization_id
42
43
  );
43
44
  if (existingUser) {
44
45
  throw new BadRequestException('User already exists');
45
46
  }
46
47
 
47
- existingUser = await this.userRepository.findByMobile(userData.mobile);
48
+ existingUser = await this.userRepository.findByMobile(
49
+ userData.mobile,
50
+ userData.organization_id
51
+ );
48
52
  if (existingUser) {
49
53
  throw new BadRequestException('User already exists');
50
54
  }
@@ -113,37 +117,63 @@ export class UserService extends EntityServiceImpl {
113
117
  entityData: BaseEntity,
114
118
  loggedInUserData: UserData,
115
119
  ): Promise<BaseEntity> {
116
- let userDto = entityData as UpdateUserDto;
117
-
120
+ const userDto = entityData as UpdateUserDto;
121
+
122
+ // Fetch the current user data from DB to get the existing encrypted password
123
+ const existingUser = await this.userRepository.findById(entityData.id);
124
+
125
+ if (!existingUser) {
126
+ throw new BadRequestException('User not found');
127
+ }
128
+
129
+ // If password is being updated, check if it's the same as existing one
118
130
  if (userDto.password) {
119
- const password = EncryptUtilService.encryptGCM(
131
+ const decryptedPassword = EncryptUtilService.decryptGCM(
132
+ existingUser.password,
133
+ this.masterKey,
134
+ this.masterIv,
135
+ );
136
+
137
+ if (decryptedPassword === userDto.password) {
138
+ throw new BadRequestException(
139
+ 'New password cannot be the same as the current password',
140
+ );
141
+ }
142
+
143
+ // Encrypt new password
144
+ const encryptedPassword = EncryptUtilService.encryptGCM(
120
145
  userDto.password,
121
146
  this.masterKey,
122
147
  this.masterIv,
123
148
  );
124
- userDto.password = password;
149
+ userDto.password = encryptedPassword;
125
150
  }
126
-
127
- let userData = plainToInstance(UserData, userDto);
128
- let savedData = await super.updateEntity(userData, loggedInUserData);
151
+
152
+ const userData = plainToInstance(UserData, userDto);
153
+
154
+ const savedData = await super.updateEntity(userData, loggedInUserData);
155
+
156
+ // Update roles if provided
129
157
  if (userDto.roles) {
130
- let roles = userDto.roles;
131
- for (const role in roles) {
132
- let userRoleMapping = new UserRoleMapping(
158
+ await this.userRoleMappingService.deleteByUserId(savedData.id); // prevent duplicates
159
+ for (const role of userDto.roles) {
160
+ const userRoleMapping = new UserRoleMapping(
133
161
  savedData.id,
134
- Number(roles[role]),
162
+ Number(role),
135
163
  );
136
164
  await this.userRoleMappingService.assignUserRole(userRoleMapping);
137
165
  }
138
166
  }
167
+
139
168
  return savedData;
140
169
  }
170
+
141
171
 
142
- async findByEmailId(email_id: string): Promise<UserData | null> {
143
- return await this.userRepository.findByEmailId(email_id);
172
+ async findByEmailId(email_id: string,organization_id?: number): Promise<UserData | null> {
173
+ return await this.userRepository.findByEmailId(email_id,organization_id);
144
174
  }
145
175
 
146
- async findByMobile(mobile: string) {
147
- return await this.userRepository.findByMobile(mobile);
176
+ async findByMobile(mobile: string,organization_id: number): Promise<UserData | null> {
177
+ return await this.userRepository.findByMobile(mobile,organization_id);
148
178
  }
149
179
  }