rez_core 2.0.47 → 2.0.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 (34) hide show
  1. package/dist/module/auth/strategies/jwt.strategy.js +1 -1
  2. package/dist/module/auth/strategies/jwt.strategy.js.map +1 -1
  3. package/dist/module/user/controller/login.controller.d.ts +10 -1
  4. package/dist/module/user/controller/login.controller.js +21 -2
  5. package/dist/module/user/controller/login.controller.js.map +1 -1
  6. package/dist/module/user/dto/create-user.dto.d.ts +1 -0
  7. package/dist/module/user/dto/create-user.dto.js.map +1 -1
  8. package/dist/module/user/repository/role.repository.d.ts +6 -0
  9. package/dist/module/user/repository/role.repository.js +27 -0
  10. package/dist/module/user/repository/role.repository.js.map +1 -1
  11. package/dist/module/user/repository/user-role-mapping.repository.d.ts +5 -1
  12. package/dist/module/user/repository/user-role-mapping.repository.js +37 -2
  13. package/dist/module/user/repository/user-role-mapping.repository.js.map +1 -1
  14. package/dist/module/user/service/role.service.js +8 -5
  15. package/dist/module/user/service/role.service.js.map +1 -1
  16. package/dist/module/user/service/user-role-mapping.service.d.ts +3 -0
  17. package/dist/module/user/service/user-role-mapping.service.js +24 -1
  18. package/dist/module/user/service/user-role-mapping.service.js.map +1 -1
  19. package/dist/module/user/service/user-session.service.d.ts +10 -1
  20. package/dist/module/user/service/user-session.service.js +24 -2
  21. package/dist/module/user/service/user-session.service.js.map +1 -1
  22. package/dist/module/user/service/user.service.js +57 -23
  23. package/dist/module/user/service/user.service.js.map +1 -1
  24. package/dist/tsconfig.build.tsbuildinfo +1 -1
  25. package/package.json +1 -1
  26. package/src/module/auth/strategies/jwt.strategy.ts +2 -2
  27. package/src/module/user/controller/login.controller.ts +32 -1
  28. package/src/module/user/dto/create-user.dto.ts +2 -0
  29. package/src/module/user/repository/role.repository.ts +46 -2
  30. package/src/module/user/repository/user-role-mapping.repository.ts +54 -1
  31. package/src/module/user/service/role.service.ts +10 -6
  32. package/src/module/user/service/user-role-mapping.service.ts +60 -0
  33. package/src/module/user/service/user-session.service.ts +140 -11
  34. package/src/module/user/service/user.service.ts +75 -65
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rez_core",
3
- "version": "2.0.47",
3
+ "version": "2.0.49",
4
4
  "description": "",
5
5
  "author": "",
6
6
  "private": false,
@@ -26,7 +26,7 @@ export class JwtStrategy extends PassportStrategy(Strategy) {
26
26
  organization_id,
27
27
  enterprise_id,
28
28
  level_id,
29
- level_type
29
+ level_type,
30
30
  } = payload;
31
31
 
32
32
  // Check if session exists and is valid
@@ -50,7 +50,7 @@ export class JwtStrategy extends PassportStrategy(Strategy) {
50
50
  organization_id: organization_id,
51
51
  enterprise_id: enterprise_id,
52
52
  level_id: level_id,
53
- level_type: level_type,
53
+ level_type: level_type,
54
54
  };
55
55
 
56
56
  return { userData };
@@ -12,10 +12,15 @@ import { LoginService } from '../service/login.service';
12
12
  import { GoogleAuthGuard } from '../../../module/auth/guards/google-auth.guard';
13
13
  import { JwtAuthGuard } from '../../auth/guards/jwt.guard';
14
14
  import { Request, Response } from 'express';
15
+ import { JwtAuthService } from 'src/module/auth/services/jwt.service';
16
+ import { UserSessionService } from '../service/user-session.service';
15
17
 
16
18
  @Controller('auth')
17
19
  export class LoginController {
18
- constructor(private loginService: LoginService) {}
20
+ constructor(
21
+ private loginService: LoginService,
22
+ private userSessionService: UserSessionService,
23
+ ) {}
19
24
 
20
25
  @Post('login')
21
26
  async login(@Body() body, @Res() res: Response) {
@@ -51,4 +56,30 @@ export class LoginController {
51
56
  // Call LoginService to validate user, create session, and return JWT
52
57
  return this.loginService.loginWithGoogle(email, name);
53
58
  }
59
+
60
+ @UseGuards(JwtAuthGuard)
61
+ @Post('switch')
62
+ async switchCurrentLevel(
63
+ @Req() req: Request & { user: any },
64
+ @Body()
65
+ data: {
66
+ level_id: string;
67
+ level_type: string;
68
+ appcode: string;
69
+ },
70
+ ): Promise<any> {
71
+ const userId = req.user.userData.id;
72
+
73
+ const currentUserLevelType = req.user.userData.level_type;
74
+ const currentUserLevelId = req.user.userData.level_id;
75
+ const currentUserOrganization_id = req.user.userData.organization_id;
76
+
77
+ return await this.userSessionService.switchCurrentLevelService(
78
+ userId,
79
+ currentUserLevelType,
80
+ currentUserLevelId,
81
+ currentUserOrganization_id,
82
+ data,
83
+ );
84
+ }
54
85
  }
@@ -57,4 +57,6 @@ export class CreateUserDto extends BaseEntity {
57
57
  is_customer: number;
58
58
  appcode: string;
59
59
  is_factory: number;
60
+
61
+ access: any[];
60
62
  }
@@ -2,8 +2,6 @@ import { BadRequestException, Injectable } from '@nestjs/common';
2
2
  import { Repository } from 'typeorm';
3
3
  import { InjectRepository } from '@nestjs/typeorm';
4
4
  import { Role } from '../entity/role.entity';
5
- import { ModuleAccess } from 'src/module/module/entity/module-access.entity';
6
- import { UserData } from '../entity/user.entity';
7
5
 
8
6
  @Injectable()
9
7
  export class RoleRepository {
@@ -49,4 +47,50 @@ export class RoleRepository {
49
47
  },
50
48
  });
51
49
  }
50
+
51
+ /*
52
+ Ensure role_code is unique within the same level_type and level_id.
53
+ * Confirm level_type and level_id correspond to existing org/school.
54
+ */
55
+
56
+ public async isRoleNameWithLevelExists(
57
+ name: string,
58
+ options?: {
59
+ excludeRoleId?: number;
60
+ organization_id?: number;
61
+ level_type?: string;
62
+ level_id?: number;
63
+ },
64
+ ): Promise<boolean> {
65
+ const query = this.roleRepo
66
+ .createQueryBuilder('role')
67
+ .where('role.name = :name', { name });
68
+
69
+ if (options?.excludeRoleId) {
70
+ query.andWhere('role.id != :excludeRoleId', {
71
+ excludeRoleId: options.excludeRoleId,
72
+ });
73
+ }
74
+
75
+ if (options?.organization_id !== undefined) {
76
+ query.andWhere('role.organization_id = :organization_id', {
77
+ organization_id: options.organization_id,
78
+ });
79
+ }
80
+
81
+ if (options?.level_type) {
82
+ query.andWhere('role.level_type = :level_type', {
83
+ level_type: options.level_type,
84
+ });
85
+ }
86
+
87
+ if (options?.level_id !== undefined) {
88
+ query.andWhere('role.level_id = :level_id', {
89
+ level_id: options.level_id,
90
+ });
91
+ }
92
+
93
+ const existingRole = await query.getOne();
94
+ return !!existingRole;
95
+ }
52
96
  }
@@ -16,6 +16,14 @@ export class UserRoleMappingRepository {
16
16
  return await this.userRoleMappingRepository.save(userRoleMapping);
17
17
  }
18
18
 
19
+ async update(
20
+ id: number,
21
+ userRoleMapping: UserRoleMapping,
22
+ ): Promise<UserRoleMapping | null> {
23
+ await this.userRoleMappingRepository.update(id, userRoleMapping);
24
+ return await this.userRoleMappingRepository.findOneBy({ id });
25
+ }
26
+
19
27
  async findByUserId(userId: number): Promise<UserRoleMapping[] | null> {
20
28
  return await this.userRoleMappingRepository.find({
21
29
  where: { user_id: userId },
@@ -31,9 +39,30 @@ export class UserRoleMappingRepository {
31
39
  async findByUserIdAndRoleId(
32
40
  userId: number,
33
41
  roleId: number,
42
+ appcode?: string,
43
+ level_id?: string,
44
+ level_type?: string,
34
45
  ): Promise<UserRoleMapping | null> {
35
46
  return await this.userRoleMappingRepository.findOne({
36
- where: { user_id: userId, role_id: roleId },
47
+ where: {
48
+ user_id: userId,
49
+ role_id: roleId,
50
+ appcode,
51
+ level_id,
52
+ level_type,
53
+ },
54
+ });
55
+ }
56
+
57
+ async findByUSRId(usrId: number): Promise<UserRoleMapping | null> {
58
+ if (usrId) {
59
+ return null;
60
+ }
61
+
62
+ return await this.userRoleMappingRepository.findOne({
63
+ where: {
64
+ id: usrId,
65
+ },
37
66
  });
38
67
  }
39
68
 
@@ -61,4 +90,28 @@ export class UserRoleMappingRepository {
61
90
 
62
91
  return { appcode: appcodeArray };
63
92
  }
93
+ async findByUserIdAndAppCode(
94
+ userId: number,
95
+ appCode: string,
96
+ ): Promise<UserRoleMapping | null> {
97
+ return await this.userRoleMappingRepository.findOne({
98
+ where: { user_id: userId, appcode: appCode },
99
+ });
100
+ }
101
+
102
+ async findByUserIdAndAppCodeAndLevel(
103
+ userId: number,
104
+ appCode: string,
105
+ levelType: string,
106
+ levelId: string,
107
+ ): Promise<UserRoleMapping | null> {
108
+ return await this.userRoleMappingRepository.findOne({
109
+ where: {
110
+ user_id: userId,
111
+ appcode: appCode,
112
+ level_type: levelType,
113
+ level_id: levelId,
114
+ },
115
+ });
116
+ }
64
117
  }
@@ -8,7 +8,6 @@ import { RoleRepository } from '../repository/role.repository';
8
8
  import { EntityManager, Repository } from 'typeorm';
9
9
  import { InjectRepository } from '@nestjs/typeorm';
10
10
  import { ModuleAccess } from '../../module/entity/module-access.entity';
11
- import { instanceToPlain } from 'class-transformer';
12
11
 
13
12
  @Injectable()
14
13
  export class RoleService extends EntityServiceImpl {
@@ -28,15 +27,20 @@ export class RoleService extends EntityServiceImpl {
28
27
  appcode?: string,
29
28
  ): Promise<BaseEntity> {
30
29
  let role = entityData as Role;
31
- if (appcode) {
32
- role.appcode = appcode;
30
+
31
+ if (loggedInUser?.level_type && loggedInUser?.level_id) {
32
+ role.level_type = loggedInUser.level_type;
33
+ role.level_id = loggedInUser.level_id;
33
34
  }
35
+
34
36
  if (
35
- await this.roleRepository.isRoleNameExists(role.name, {
36
- organization_id: entityData.organization_id,
37
+ await this.roleRepository.isRoleNameWithLevelExists(role.name, {
38
+ organization_id: loggedInUser?.organization_id || undefined,
39
+ level_type: loggedInUser?.level_type,
40
+ level_id: parseInt(loggedInUser?.level_id || '', 10),
37
41
  })
38
42
  ) {
39
- throw new BadRequestException('Role name already exists.');
43
+ throw new BadRequestException('Role code already exists.');
40
44
  }
41
45
 
42
46
  const sourceRole = role.copy_from_role_id
@@ -12,6 +12,9 @@ export class UserRoleMappingService {
12
12
  const existing = await this.userRoleMappingRepository.findByUserIdAndRoleId(
13
13
  userRoleMapping.user_id,
14
14
  userRoleMapping.role_id,
15
+ userRoleMapping.appcode,
16
+ userRoleMapping.level_id,
17
+ userRoleMapping.level_type,
15
18
  );
16
19
 
17
20
  if (!existing) {
@@ -19,6 +22,39 @@ export class UserRoleMappingService {
19
22
  }
20
23
  }
21
24
 
25
+ async updateAssignedRole(userRoleMapping: UserRoleMapping) {
26
+ // 1. If ID is provided, try to fetch existing mapping by ID
27
+ if (userRoleMapping.id) {
28
+ const existing = await this.userRoleMappingRepository.findByUSRId(
29
+ userRoleMapping.id,
30
+ );
31
+ if (existing) {
32
+ existing.appcode = userRoleMapping.appcode;
33
+ existing.level_id = userRoleMapping.level_id;
34
+ existing.level_type = userRoleMapping.level_type;
35
+ existing.role_id = userRoleMapping.role_id;
36
+
37
+ return await this.userRoleMappingRepository.save(existing);
38
+ }
39
+ }
40
+
41
+ // 2. Check if a similar mapping already exists (same user-role-level-app)
42
+ const duplicate =
43
+ await this.userRoleMappingRepository.findByUserIdAndRoleId(
44
+ userRoleMapping.user_id,
45
+ userRoleMapping.role_id,
46
+ userRoleMapping.appcode,
47
+ userRoleMapping.level_id,
48
+ userRoleMapping.level_type,
49
+ );
50
+
51
+ if (duplicate) {
52
+ return duplicate; // or null, depending on how you want to handle it
53
+ }
54
+
55
+ return await this.userRoleMappingRepository.save(userRoleMapping);
56
+ }
57
+
22
58
  async findByUserId(userId: number): Promise<UserRoleMapping[] | null> {
23
59
  return await this.userRoleMappingRepository.findByUserId(userId);
24
60
  }
@@ -26,4 +62,28 @@ export class UserRoleMappingService {
26
62
  async deleteByUserId(userId: number) {
27
63
  await this.userRoleMappingRepository.deleteByUserId(userId);
28
64
  }
65
+
66
+ async getUserByIdAndAppCode(
67
+ userId: number,
68
+ appCode: string,
69
+ ): Promise<UserRoleMapping | null> {
70
+ return await this.userRoleMappingRepository.findByUserIdAndAppCode(
71
+ userId,
72
+ appCode,
73
+ );
74
+ }
75
+
76
+ async getUserByIdAppCodeAndLevel(
77
+ userId: number,
78
+ appCode: string,
79
+ levelType: string,
80
+ levelId: string,
81
+ ): Promise<UserRoleMapping | null> {
82
+ return await this.userRoleMappingRepository.findByUserIdAndAppCodeAndLevel(
83
+ userId,
84
+ appCode,
85
+ levelType,
86
+ levelId,
87
+ );
88
+ }
29
89
  }
@@ -1,9 +1,11 @@
1
1
  import { UserSession } from '../entity/user-session.entity';
2
2
  import { ClockIDGenService } from '../../../utils/service/clockIDGenUtil.service';
3
- import { Injectable } from '@nestjs/common';
3
+ import { BadRequestException, Injectable } from '@nestjs/common';
4
4
  import { UserSessionRepository } from '../repository/userSession.repository';
5
5
  import { JwtAuthService } from 'src/module/auth/services/jwt.service';
6
6
  import { ConfigService } from '@nestjs/config';
7
+ import { UserRoleMappingService } from './user-role-mapping.service';
8
+ import { DataSource } from 'typeorm';
7
9
 
8
10
  @Injectable()
9
11
  export class UserSessionService {
@@ -12,48 +14,51 @@ export class UserSessionService {
12
14
  private readonly jwtAuthService: JwtAuthService,
13
15
  private readonly clockIDGenService: ClockIDGenService,
14
16
  private configService: ConfigService,
17
+ private readonly userRoleMappingService: UserRoleMappingService,
18
+ private readonly dataSource: DataSource, // Assuming dataSource is injected for TypeORM operations
15
19
  ) {}
16
20
  async createSession(user, appcode?: string, accessInfo?: any) {
17
21
  const sessionToken = this.clockIDGenService.idGenerator('SES');
18
-
22
+
19
23
  const userSession: any = new UserSession();
20
24
  userSession.user_id = user.id;
21
25
  userSession.session_key = sessionToken;
22
26
  userSession.is_session_loggedout = 0;
23
27
  userSession.login_time = new Date();
24
-
28
+
25
29
  const expiryTokenInHours = this.configService.get('TOKEN_EXPIRY') || 1;
26
30
  userSession.expiry_date = new Date(
27
31
  Date.now() + expiryTokenInHours * 60 * 60 * 1000,
28
32
  );
29
-
33
+
30
34
  await this.userSessionRepository.saveSession(userSession);
31
-
35
+
32
36
  const payload: any = {
33
37
  userId: user.id,
34
38
  sessionToken,
35
39
  appcode,
36
40
  email_id: user.email_id,
41
+ level_type: user.level_type,
42
+ level_id: user.level_id,
37
43
  organization_id: user.organization_id,
38
44
  enterprise_id: user.enterprise_id,
39
45
  };
40
-
46
+
41
47
  // ✅ Add role access details
42
48
  if (accessInfo) {
43
49
  payload.level_type = accessInfo.level_type;
44
50
  payload.level_id = accessInfo.level_id;
45
51
  payload.role_id = accessInfo.role_id;
46
- payload.role_code = accessInfo.role_code;
52
+ payload.role_code = accessInfo.role_code;
47
53
  }
48
-
54
+
49
55
  const accessToken = this.jwtAuthService.generateJwt(payload);
50
-
56
+
51
57
  userSession.access_token = accessToken;
52
58
  await this.userSessionRepository.saveSession(userSession);
53
-
59
+
54
60
  return accessToken;
55
61
  }
56
-
57
62
 
58
63
  async findBySessionKey(sessionKey: string): Promise<UserSession | null> {
59
64
  return await this.userSessionRepository.findBySessionKey(sessionKey);
@@ -62,4 +67,128 @@ export class UserSessionService {
62
67
  async updateSession(userSession: UserSession) {
63
68
  await this.userSessionRepository.saveSession(userSession);
64
69
  }
70
+
71
+ async switchCurrentLevelService(
72
+ userId: number,
73
+ currentUserLevelType: string,
74
+ currentUserLevelId: string,
75
+ currentUserOrgId: number,
76
+ data: any,
77
+ ): Promise<{ success: boolean; access_token: string; appcode: string }> {
78
+ let payload;
79
+
80
+ // Step 1: App-level access check
81
+ // if (data.appcode) {
82
+ // console.log('in appcode check', data.appcode);
83
+
84
+ // const userApp = await this.userRoleMappingService.getUserByIdAndAppCode(
85
+ // userId,
86
+ // data.appcode,
87
+ // );
88
+
89
+ // if (!userApp) {
90
+ // throw new BadRequestException(
91
+ // 'User does not have access to this appcode',
92
+ // );
93
+ // }
94
+
95
+ payload = {
96
+ id: userId,
97
+ level_id: currentUserLevelId,
98
+ level_type: currentUserLevelType,
99
+ appcode: data.appcode,
100
+ };
101
+ // }
102
+
103
+ // Step 2: Level switch logic
104
+ // if (data.level_id && data.level_type) {
105
+ // console.log(
106
+ // 'in level_id and level_type check',
107
+ // data.level_id,
108
+ // data.level_type,
109
+ // );
110
+
111
+ // console.log(
112
+ // 'Current User Level Type:',
113
+ // currentUserLevelType,
114
+ // 'Current User Level ID:',
115
+ // currentUserLevelId,
116
+ // );
117
+
118
+ // const hasAccess = await this.dataSource.query(
119
+ // 'SELECT * FROM cr_user_role_mapping WHERE user_id = ? AND level_type = ? AND level_id = ? AND appcode = ?',
120
+ // [userId, data.level_type, data.level_id, data.appcode || null],
121
+ // );
122
+
123
+ // console.log('Has Access:', hasAccess);
124
+
125
+ // // check if hasAccess is non-empty
126
+ // if (hasAccess.length) {
127
+ // payload = {
128
+ // id: userId,
129
+ // level_id: data.level_id,
130
+ // level_type: data.level_type,
131
+ // appcode: data.appcode || null,
132
+ // };
133
+ // }
134
+ // } else if (currentUserLevelType === 'ORG') {
135
+ // const school = await this.dataSource.query(
136
+ // 'SELECT * FROM cr_school WHERE id = ?',
137
+ // [data.level_id],
138
+ // );
139
+
140
+ // console.log('Current User Org ID:', currentUserOrgId);
141
+ // console.log('Data Level Type:', data.level_type);
142
+ // console.log('School:', school);
143
+
144
+ // if (!school.length || currentUserOrgId !== school[0].organization_id) {
145
+ // throw new BadRequestException(
146
+ // 'You do not have access to this school',
147
+ // );
148
+ // }
149
+
150
+ // payload = {
151
+ // id: userId,
152
+ // level_id: data.level_id,
153
+ // level_type: data.level_type,
154
+ // appcode: data.appcode || null,
155
+ // };
156
+ // } else if (currentUserLevelType === 'BRN') {
157
+ // console.log('Current User Level Type is BRN');
158
+
159
+ // const school = await this.dataSource.query(
160
+ // 'SELECT * FROM cr_school WHERE id = ?',
161
+ // [data.level_id],
162
+ // );
163
+
164
+ // console.log('school:', school);
165
+
166
+ // if (!school.length || school[0].brand_id !== currentUserLevelId) {
167
+ // throw new BadRequestException(
168
+ // 'You do not have access to this school',
169
+ // );
170
+ // }
171
+
172
+ // payload = {
173
+ // id: userId,
174
+ // level_id: data.level_id,
175
+ // level_type: data.level_type,
176
+ // appcode: data.appcode || null,
177
+ // };
178
+ // }
179
+ // else {
180
+ // throw new BadRequestException('You do not have access to this level');
181
+ // }
182
+ // }
183
+
184
+ // if (!payload) {
185
+ // throw new BadRequestException('Invalid request parameters');
186
+ // }
187
+
188
+ return {
189
+ success: true,
190
+ access_token: this.jwtAuthService.generateJwt(payload),
191
+ appcode: data.appcode,
192
+ };
193
+ }
65
194
  }