rez_core 2.0.53 → 2.0.55
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/module/module/controller/menu.controller.js +2 -3
- package/dist/module/module/controller/menu.controller.js.map +1 -1
- package/dist/module/module/entity/menu.entity.d.ts +1 -0
- package/dist/module/module/entity/menu.entity.js +4 -0
- package/dist/module/module/entity/menu.entity.js.map +1 -1
- package/dist/module/module/repository/menu.repository.d.ts +4 -2
- package/dist/module/module/repository/menu.repository.js +61 -7
- package/dist/module/module/repository/menu.repository.js.map +1 -1
- package/dist/module/module/service/menu.service.d.ts +4 -2
- package/dist/module/module/service/menu.service.js +10 -9
- package/dist/module/module/service/menu.service.js.map +1 -1
- package/dist/module/user/service/login.service.js +1 -1
- package/dist/module/user/service/login.service.js.map +1 -1
- package/dist/resources/dev.properties.yaml +23 -0
- package/dist/resources/uat.properties.yaml +16 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/module/module/controller/menu.controller.ts +3 -3
- package/src/module/module/entity/menu.entity.ts +3 -0
- package/src/module/module/repository/menu.repository.ts +77 -25
- package/src/module/module/service/menu.service.ts +28 -26
- package/src/module/user/service/login.service.ts +1 -1
package/package.json
CHANGED
|
@@ -9,8 +9,8 @@ export class MenuController {
|
|
|
9
9
|
@UseGuards(JwtAuthGuard)
|
|
10
10
|
@Get()
|
|
11
11
|
async getMenu(@Request() req) {
|
|
12
|
-
const userId = req.user.userData
|
|
13
|
-
|
|
14
|
-
return this.menuService.getUserMenu(userId, appcode);
|
|
12
|
+
const { id: userId, appcode, level_type, level_id } = req.user.userData;
|
|
13
|
+
return this.menuService.getUserMenu(userId, appcode, level_type, level_id);
|
|
15
14
|
}
|
|
15
|
+
|
|
16
16
|
}
|
|
@@ -4,21 +4,21 @@ import { MenuData } from '../entity/menu.entity';
|
|
|
4
4
|
import { ModuleAccess } from '../entity/module-access.entity';
|
|
5
5
|
import { UserRoleMapping } from 'src/module/user/entity/user-role-mapping.entity';
|
|
6
6
|
import { Role } from 'src/module/user/entity/role.entity';
|
|
7
|
+
import { InjectRepository } from '@nestjs/typeorm';
|
|
7
8
|
|
|
8
9
|
@Injectable()
|
|
9
10
|
export class MenuRepository extends Repository<MenuData> {
|
|
10
|
-
constructor(private readonly dataSource: DataSource
|
|
11
|
+
constructor(private readonly dataSource: DataSource,
|
|
12
|
+
@InjectRepository(MenuData) private readonly menuData: Repository<MenuData>
|
|
13
|
+
) {
|
|
11
14
|
super(MenuData, dataSource.createEntityManager());
|
|
12
15
|
}
|
|
13
16
|
|
|
14
|
-
/**
|
|
15
|
-
* Get all role IDs assigned to a user.
|
|
16
|
-
*/
|
|
17
17
|
async getUserRoles(userId: number, appcode: string): Promise<number[]> {
|
|
18
18
|
const roles = await this.dataSource
|
|
19
19
|
.getRepository(UserRoleMapping)
|
|
20
20
|
.createQueryBuilder('urm')
|
|
21
|
-
.innerJoin('cr_role', 'role', 'role.id = urm.role_id')
|
|
21
|
+
.innerJoin('cr_role', 'role', 'role.id = urm.role_id')
|
|
22
22
|
.select('urm.role_id')
|
|
23
23
|
.where('urm.user_id = :userId', { userId })
|
|
24
24
|
.andWhere('role.appcode = :appcode', { appcode })
|
|
@@ -27,13 +27,7 @@ export class MenuRepository extends Repository<MenuData> {
|
|
|
27
27
|
return roles.map((r) => r.urm_role_id);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
* Get module codes that the user has access to based on their role IDs.
|
|
32
|
-
*/ async getAccessibleModules(
|
|
33
|
-
roleIds: number[],
|
|
34
|
-
appCode: string,
|
|
35
|
-
): Promise<string[]> {
|
|
36
|
-
// Get role codes from role IDs
|
|
30
|
+
async getAccessibleModules(roleIds: number[], appCode: string): Promise<string[]> {
|
|
37
31
|
const roleCodes = await this.dataSource
|
|
38
32
|
.getRepository(Role)
|
|
39
33
|
.createQueryBuilder('role')
|
|
@@ -42,32 +36,29 @@ export class MenuRepository extends Repository<MenuData> {
|
|
|
42
36
|
.getMany();
|
|
43
37
|
|
|
44
38
|
const codes = roleCodes.map((role) => role.code);
|
|
39
|
+
if (codes.length === 0) return [];
|
|
45
40
|
|
|
46
|
-
if (codes.length === 0) {
|
|
47
|
-
return [];
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// Get accessible modules using role codes and appCode
|
|
51
41
|
const modules = await this.dataSource
|
|
52
42
|
.getRepository(ModuleAccess)
|
|
53
43
|
.createQueryBuilder('moduleAccess')
|
|
54
44
|
.select('moduleAccess.module_code')
|
|
55
45
|
.where('moduleAccess.role_code IN (:...codes)', { codes })
|
|
56
46
|
.andWhere('moduleAccess.access_flag > 0')
|
|
57
|
-
.andWhere('LOWER(moduleAccess.appcode) = LOWER(:appCode)', { appCode })
|
|
47
|
+
.andWhere('LOWER(moduleAccess.appcode) = LOWER(:appCode)', { appCode })
|
|
58
48
|
.getMany();
|
|
59
49
|
|
|
60
50
|
return modules.map((module) => module.module_code);
|
|
61
51
|
}
|
|
62
52
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
53
|
+
/**
|
|
54
|
+
* ✅ FIXED: Use this.createQueryBuilder() instead of this.menuData.createQueryBuilder()
|
|
55
|
+
*/
|
|
56
|
+
async getMenuItems(moduleCodes: string[], appcode: string, levelType: string) {
|
|
57
|
+
return await this.menuData.createQueryBuilder('menu')
|
|
68
58
|
.leftJoin('cr_module', 'module', 'menu.module_code = module.module_code')
|
|
69
59
|
.where('menu.module_code IN (:...moduleCodes)', { moduleCodes })
|
|
70
|
-
.andWhere('LOWER(module.appcode) = LOWER(:appcode)', { appcode })
|
|
60
|
+
.andWhere('LOWER(module.appcode) = LOWER(:appcode)', { appcode })
|
|
61
|
+
.andWhere('menu.level_type = :levelType', { levelType })
|
|
71
62
|
.select([
|
|
72
63
|
'menu.*',
|
|
73
64
|
'module.component_name AS component',
|
|
@@ -77,7 +68,68 @@ export class MenuRepository extends Repository<MenuData> {
|
|
|
77
68
|
'module.ui_config AS ui_config',
|
|
78
69
|
])
|
|
79
70
|
.getRawMany();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
async resolveUserRoles(
|
|
75
|
+
userId: number,
|
|
76
|
+
appcode: string,
|
|
77
|
+
levelType: string,
|
|
78
|
+
levelId: number,
|
|
79
|
+
): Promise<number[]> {
|
|
80
|
+
const repo = this.dataSource.getRepository(UserRoleMapping);
|
|
81
|
+
|
|
82
|
+
// 1. Try exact level match
|
|
83
|
+
let roles = await repo.createQueryBuilder('urm')
|
|
84
|
+
.innerJoin('cr_role', 'role', 'role.id = urm.role_id')
|
|
85
|
+
.select('urm.role_id')
|
|
86
|
+
.where('urm.user_id = :userId', { userId })
|
|
87
|
+
.andWhere('urm.level_type = :levelType', { levelType })
|
|
88
|
+
.andWhere('urm.level_id = :levelId', { levelId })
|
|
89
|
+
.andWhere('role.appcode = :appcode', { appcode })
|
|
90
|
+
.getRawMany();
|
|
91
|
+
|
|
92
|
+
if (roles.length) return roles.map(r => r.urm_role_id);
|
|
93
|
+
|
|
94
|
+
// 2. If SCH fallback → BRN → ORG
|
|
95
|
+
if (levelType === 'SCH') {
|
|
96
|
+
const [sch] = await this.dataSource.query(`
|
|
97
|
+
SELECT s.brn_id, b.org_id
|
|
98
|
+
FROM cr_school s
|
|
99
|
+
LEFT JOIN cr_branch b ON s.brn_id = b.id
|
|
100
|
+
WHERE s.id = $1
|
|
101
|
+
`, [levelId]);
|
|
102
|
+
|
|
103
|
+
const branchId = sch?.brn_id;
|
|
104
|
+
const orgId = sch?.org_id;
|
|
105
|
+
|
|
106
|
+
if (branchId) {
|
|
107
|
+
roles = await repo.createQueryBuilder('urm')
|
|
108
|
+
.innerJoin('cr_role', 'role', 'role.id = urm.role_id')
|
|
109
|
+
.select('urm.role_id')
|
|
110
|
+
.where('urm.user_id = :userId', { userId })
|
|
111
|
+
.andWhere('urm.level_type = :levelType', { levelType: 'BRN' })
|
|
112
|
+
.andWhere('urm.level_id = :levelId', { levelId: branchId })
|
|
113
|
+
.andWhere('role.appcode = :appcode', { appcode })
|
|
114
|
+
.getRawMany();
|
|
115
|
+
|
|
116
|
+
if (roles.length) return roles.map(r => r.urm_role_id);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (orgId) {
|
|
120
|
+
roles = await repo.createQueryBuilder('urm')
|
|
121
|
+
.innerJoin('cr_role', 'role', 'role.id = urm.role_id')
|
|
122
|
+
.select('urm.role_id')
|
|
123
|
+
.where('urm.user_id = :userId', { userId })
|
|
124
|
+
.andWhere('urm.level_type = :levelType', { levelType: 'ORG' })
|
|
125
|
+
.andWhere('urm.level_id = :levelId', { levelId: orgId })
|
|
126
|
+
.andWhere('role.appcode = :appcode', { appcode })
|
|
127
|
+
.getRawMany();
|
|
128
|
+
|
|
129
|
+
if (roles.length) return roles.map(r => r.urm_role_id);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
80
132
|
|
|
81
|
-
return
|
|
133
|
+
return [];
|
|
82
134
|
}
|
|
83
135
|
}
|
|
@@ -1,42 +1,40 @@
|
|
|
1
1
|
import { Injectable } from '@nestjs/common';
|
|
2
2
|
import { MenuRepository } from '../repository/menu.repository';
|
|
3
3
|
import { MenuData } from '../entity/menu.entity';
|
|
4
|
+
import { DataSource } from 'typeorm';
|
|
5
|
+
import { UserRoleMapping } from 'src/module/user/entity/user-role-mapping.entity';
|
|
4
6
|
|
|
5
7
|
@Injectable()
|
|
6
8
|
export class MenuService {
|
|
7
|
-
constructor(private readonly menuRepository: MenuRepository
|
|
9
|
+
constructor(private readonly menuRepository: MenuRepository,
|
|
10
|
+
private readonly datasource:DataSource
|
|
11
|
+
) {}
|
|
8
12
|
|
|
9
13
|
/**
|
|
10
14
|
* Fetch and construct menu hierarchy for a given user.
|
|
11
15
|
*/
|
|
12
|
-
async getUserMenu(
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
);
|
|
24
|
-
if (!moduleCodes.length) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
moduleCodes,
|
|
31
|
-
appcode,
|
|
32
|
-
);
|
|
33
|
-
|
|
34
|
-
// Step 4: Build hierarchical menu structure
|
|
16
|
+
async getUserMenu(
|
|
17
|
+
userId: number,
|
|
18
|
+
appcode: string,
|
|
19
|
+
levelType: 'ORG' | 'SCH',
|
|
20
|
+
levelId: number,
|
|
21
|
+
): Promise<{ menu: any[] }> {
|
|
22
|
+
// Step 1: Resolve roles (with fallback logic inside)
|
|
23
|
+
const roleCodes = await this.menuRepository.resolveUserRoles(userId, appcode, levelType, levelId);
|
|
24
|
+
if (!roleCodes.length) return { menu: [] };
|
|
25
|
+
|
|
26
|
+
// Step 2: Get accessible modules
|
|
27
|
+
const moduleCodes = await this.menuRepository.getAccessibleModules(roleCodes, appcode);
|
|
28
|
+
if (!moduleCodes.length) return { menu: [] };
|
|
29
|
+
|
|
30
|
+
// Step 3: Get menu items for the given level type
|
|
31
|
+
const menuItems = await this.menuRepository.getMenuItems(moduleCodes, appcode, levelType);
|
|
32
|
+
|
|
33
|
+
// Step 4: Build hierarchy
|
|
35
34
|
const menuTree = this.buildMenuHierarchy(menuItems);
|
|
36
|
-
|
|
37
35
|
return { menu: menuTree };
|
|
38
36
|
}
|
|
39
|
-
|
|
37
|
+
|
|
40
38
|
/**
|
|
41
39
|
* Converts a flat list of menu items into a hierarchical tree.
|
|
42
40
|
*/
|
|
@@ -67,4 +65,8 @@ export class MenuService {
|
|
|
67
65
|
async getUserRoles(userId: number, appcode: string): Promise<any> {
|
|
68
66
|
return this.menuRepository.getUserRoles(userId, appcode);
|
|
69
67
|
}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
|
|
70
72
|
}
|