rez_core 2.1.23 → 2.1.25
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/enterprise/controller/organization.controller.d.ts +3 -1
- package/dist/module/enterprise/controller/organization.controller.js +6 -3
- package/dist/module/enterprise/controller/organization.controller.js.map +1 -1
- package/dist/module/enterprise/repository/school.repository.d.ts +1 -1
- package/dist/module/enterprise/repository/school.repository.js +122 -68
- package/dist/module/enterprise/repository/school.repository.js.map +1 -1
- package/dist/module/enterprise/service/organization.service.d.ts +1 -1
- package/dist/module/enterprise/service/organization.service.js +2 -2
- package/dist/module/enterprise/service/organization.service.js.map +1 -1
- package/dist/module/module/service/module-access.service.js +9 -1
- package/dist/module/module/service/module-access.service.js.map +1 -1
- package/dist/module/user/entity/user.entity.d.ts +2 -0
- package/dist/module/user/entity/user.entity.js +8 -0
- package/dist/module/user/entity/user.entity.js.map +1 -1
- package/dist/module/user/service/login.service.d.ts +2 -2
- package/dist/module/user/service/login.service.js +22 -10
- package/dist/module/user/service/login.service.js.map +1 -1
- package/dist/module/user/service/user-session.service.js +1 -1
- package/dist/module/user/service/user-session.service.js.map +1 -1
- package/dist/module/user/service/user.service.d.ts +1 -0
- package/dist/module/user/service/user.service.js +9 -0
- package/dist/module/user/service/user.service.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/module/enterprise/controller/organization.controller.ts +5 -2
- package/src/module/enterprise/repository/school.repository.ts +148 -75
- package/src/module/enterprise/service/organization.service.ts +2 -2
- package/src/module/module/service/module-access.service.ts +28 -1
- package/src/module/user/entity/user.entity.ts +6 -0
- package/src/module/user/service/login.service.ts +33 -17
- package/src/module/user/service/user-session.service.ts +2 -2
- package/src/module/user/service/user.service.ts +17 -0
package/package.json
CHANGED
|
@@ -23,7 +23,10 @@ export class OrganizationController {
|
|
|
23
23
|
|
|
24
24
|
@UseGuards(JwtAuthGuard)
|
|
25
25
|
@Get('hierarchy')
|
|
26
|
-
async getOrganizationHierarchy():
|
|
27
|
-
|
|
26
|
+
async getOrganizationHierarchy(@Req() req: Request & { user: any }) {
|
|
27
|
+
const userId = req.user.userData?.id;
|
|
28
|
+
const appcode = req.user.userData?.appcode;
|
|
29
|
+
|
|
30
|
+
return await this.orgService.getOrganizationHierarchy(userId, appcode);
|
|
28
31
|
}
|
|
29
32
|
}
|
|
@@ -24,93 +24,166 @@ export class SchoolRepository {
|
|
|
24
24
|
});
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
async getUserContextDropdown(
|
|
28
|
-
const
|
|
29
|
-
.createQueryBuilder()
|
|
30
|
-
.select([
|
|
31
|
-
'org.id AS org_id',
|
|
32
|
-
'org.name AS org_name',
|
|
33
|
-
'org.address AS org_address',
|
|
34
|
-
'org.type AS org_type',
|
|
35
|
-
|
|
36
|
-
// Full brand columns
|
|
37
|
-
'br.id AS brand_id',
|
|
38
|
-
'br.entity_type AS brand_entity_type',
|
|
39
|
-
'br.name AS brand_name',
|
|
40
|
-
'br.status AS brand_status',
|
|
41
|
-
'br.parent_type AS brand_parent_type',
|
|
42
|
-
'br.parent_id AS brand_parent_id',
|
|
43
|
-
'br.code AS brand_code',
|
|
44
|
-
'br.enterprise_id AS brand_enterprise_id',
|
|
45
|
-
'br.organization_id AS brand_organization_id',
|
|
46
|
-
'br.appcode AS brand_appcode',
|
|
47
|
-
'br.level_id AS brand_level_id',
|
|
48
|
-
'br.level_type AS brand_level_type',
|
|
49
|
-
'br.type AS brand_type',
|
|
50
|
-
|
|
51
|
-
// Full school columns
|
|
52
|
-
'sch.id AS school_id',
|
|
53
|
-
'sch.entity_type AS school_entity_type',
|
|
54
|
-
'sch.name AS school_name',
|
|
55
|
-
'sch.status AS school_status',
|
|
56
|
-
'sch.parent_type AS school_parent_type',
|
|
57
|
-
'sch.parent_id AS school_parent_id',
|
|
58
|
-
'sch.code AS school_code',
|
|
59
|
-
'sch.enterprise_id AS school_enterprise_id',
|
|
60
|
-
'sch.organization_id AS school_organization_id',
|
|
61
|
-
'sch.appcode AS school_appcode',
|
|
62
|
-
'sch.level_id AS school_level_id',
|
|
63
|
-
'sch.level_type AS school_level_type',
|
|
64
|
-
'sch.type AS school_type',
|
|
65
|
-
])
|
|
66
|
-
.from('cr_school', 'sch')
|
|
67
|
-
.innerJoin('cr_brand', 'br', 'sch.brand_id = br.id')
|
|
68
|
-
.innerJoin('cr_organization', 'org', 'br.organization_id = org.id')
|
|
69
|
-
.orderBy('org.id, br.id, sch.id')
|
|
70
|
-
.getRawMany();
|
|
71
|
-
|
|
72
|
-
const result = {};
|
|
27
|
+
async getUserContextDropdown(userId: number, appCode: string) {
|
|
28
|
+
const userRoleRepo = this.dataSource.getRepository(UserRoleMapping);
|
|
73
29
|
|
|
74
|
-
|
|
75
|
-
|
|
30
|
+
const hasOrgAccess = await userRoleRepo
|
|
31
|
+
.createQueryBuilder('urm')
|
|
32
|
+
.where('urm.user_id = :userId', { userId })
|
|
33
|
+
.andWhere('urm.appcode = :appCode', { appCode })
|
|
34
|
+
.andWhere('urm.level_type = :levelType', { levelType: 'ORG' })
|
|
35
|
+
.getRawMany();
|
|
76
36
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
37
|
+
if (hasOrgAccess.length > 0) {
|
|
38
|
+
const schools = await this.dataSource
|
|
39
|
+
.createQueryBuilder()
|
|
40
|
+
.select([
|
|
41
|
+
'org.id AS org_id',
|
|
42
|
+
'org.name AS org_name',
|
|
43
|
+
'org.address AS org_address',
|
|
44
|
+
'org.status AS org_status',
|
|
45
|
+
'br.id AS brand_id',
|
|
46
|
+
'br.name AS brand_name',
|
|
47
|
+
'br.status AS brand_status',
|
|
48
|
+
'sch.id AS school_id',
|
|
49
|
+
'sch.name AS school_name',
|
|
50
|
+
'sch.location AS school_location',
|
|
51
|
+
'sch.status AS school_status',
|
|
52
|
+
])
|
|
53
|
+
.from('cr_school', 'sch')
|
|
54
|
+
.innerJoin('cr_brand', 'br', 'sch.brand_id = br.id')
|
|
55
|
+
.innerJoin('cr_organization', 'org', 'br.organization_id = org.id')
|
|
56
|
+
.where('org.id = :orgId', { orgId: hasOrgAccess[0].urm_level_id })
|
|
57
|
+
.getRawMany();
|
|
80
58
|
|
|
81
|
-
|
|
82
|
-
|
|
59
|
+
const result = {};
|
|
60
|
+
for (const row of schools) {
|
|
61
|
+
const {
|
|
83
62
|
org_id,
|
|
84
63
|
org_name,
|
|
85
64
|
org_address,
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
65
|
+
org_status,
|
|
66
|
+
brand_id,
|
|
67
|
+
brand_name,
|
|
68
|
+
brand_status,
|
|
69
|
+
school_id,
|
|
70
|
+
school_name,
|
|
71
|
+
school_location,
|
|
72
|
+
school_status,
|
|
73
|
+
} = row;
|
|
90
74
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
75
|
+
if (!result[org_id]) {
|
|
76
|
+
result[org_id] = {
|
|
77
|
+
org_id,
|
|
78
|
+
org_name,
|
|
79
|
+
org_address,
|
|
80
|
+
status: org_status,
|
|
81
|
+
type: 'Organization',
|
|
82
|
+
brands: {},
|
|
83
|
+
};
|
|
97
84
|
}
|
|
98
|
-
|
|
99
|
-
result[org_id].brands[brand_id]
|
|
85
|
+
|
|
86
|
+
if (!result[org_id].brands[brand_id]) {
|
|
87
|
+
result[org_id].brands[brand_id] = {
|
|
88
|
+
brand_id,
|
|
89
|
+
brand_name,
|
|
90
|
+
status: brand_status,
|
|
91
|
+
type: 'Brand',
|
|
92
|
+
schools: [],
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
result[org_id].brands[brand_id].schools.push({
|
|
97
|
+
school_id,
|
|
98
|
+
school_name,
|
|
99
|
+
school_location,
|
|
100
|
+
status: school_status,
|
|
101
|
+
type: 'School',
|
|
102
|
+
});
|
|
100
103
|
}
|
|
101
104
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
105
|
+
return Object.values(result).map((org: any) => ({
|
|
106
|
+
...org,
|
|
107
|
+
brands: Object.values(org.brands),
|
|
108
|
+
}));
|
|
109
|
+
} else {
|
|
110
|
+
const brnMappings = await this.dataSource
|
|
111
|
+
.createQueryBuilder()
|
|
112
|
+
.select([
|
|
113
|
+
'brand.id AS brand_id',
|
|
114
|
+
'brand.name AS brand_name',
|
|
115
|
+
'brand.status AS brand_status',
|
|
116
|
+
'school.id AS school_id',
|
|
117
|
+
'school.name AS school_name',
|
|
118
|
+
'school.location AS school_location',
|
|
119
|
+
'school.status AS school_status',
|
|
120
|
+
])
|
|
121
|
+
.from('cr_user_role_mapping', 'urm')
|
|
122
|
+
.innerJoin('cr_brand', 'brand', 'brand.id = urm.level_id')
|
|
123
|
+
.innerJoin('cr_school', 'school', 'school.brand_id = brand.id')
|
|
124
|
+
.where('urm.user_id = :userId', { userId })
|
|
125
|
+
.andWhere('urm.appcode = :appCode', { appCode })
|
|
126
|
+
.andWhere('urm.level_type = :levelType', { levelType: 'BRN' })
|
|
127
|
+
.getRawMany();
|
|
128
|
+
|
|
129
|
+
const schMappings = await this.dataSource
|
|
130
|
+
.createQueryBuilder()
|
|
131
|
+
.select([
|
|
132
|
+
'brand.id AS brand_id',
|
|
133
|
+
'brand.name AS brand_name',
|
|
134
|
+
'brand.status AS brand_status',
|
|
135
|
+
'school.id AS school_id',
|
|
136
|
+
'school.name AS school_name',
|
|
137
|
+
'school.location AS school_location',
|
|
138
|
+
'school.status AS school_status',
|
|
139
|
+
])
|
|
140
|
+
.from('cr_user_role_mapping', 'urm')
|
|
141
|
+
.innerJoin('cr_school', 'school', 'school.id = urm.level_id')
|
|
142
|
+
.innerJoin('cr_brand', 'brand', 'brand.id = school.brand_id')
|
|
143
|
+
.where('urm.user_id = :userId', { userId })
|
|
144
|
+
.andWhere('urm.appcode = :appCode', { appCode })
|
|
145
|
+
.andWhere('urm.level_type = :levelType', { levelType: 'SCH' })
|
|
146
|
+
.getRawMany();
|
|
147
|
+
|
|
148
|
+
const allMappings = [...brnMappings, ...schMappings];
|
|
149
|
+
|
|
150
|
+
const result = {};
|
|
151
|
+
for (const row of allMappings) {
|
|
152
|
+
const {
|
|
153
|
+
brand_id,
|
|
154
|
+
brand_name,
|
|
155
|
+
brand_status,
|
|
156
|
+
school_id,
|
|
157
|
+
school_name,
|
|
158
|
+
school_location,
|
|
159
|
+
school_status,
|
|
160
|
+
} = row;
|
|
161
|
+
|
|
162
|
+
if (!result[brand_id]) {
|
|
163
|
+
result[brand_id] = {
|
|
164
|
+
brand_id,
|
|
165
|
+
brand_name,
|
|
166
|
+
status: brand_status,
|
|
167
|
+
type: 'Brand',
|
|
168
|
+
schools: [],
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (
|
|
173
|
+
school_id &&
|
|
174
|
+
!result[brand_id].schools.some((s) => s.school_id === school_id)
|
|
175
|
+
) {
|
|
176
|
+
result[brand_id].schools.push({
|
|
177
|
+
school_id,
|
|
178
|
+
school_name,
|
|
179
|
+
school_location,
|
|
180
|
+
status: school_status,
|
|
181
|
+
type: 'School',
|
|
182
|
+
});
|
|
106
183
|
}
|
|
107
184
|
}
|
|
108
|
-
result[org_id].brands[brand_id].schools.push(schoolInfo);
|
|
109
|
-
}
|
|
110
185
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
brands: Object.values(org.brands),
|
|
114
|
-
}));
|
|
186
|
+
return Object.values(result);
|
|
187
|
+
}
|
|
115
188
|
}
|
|
116
189
|
}
|
|
@@ -78,7 +78,7 @@ export class OrganizationService {
|
|
|
78
78
|
await repo.delete(id);
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
async getOrganizationHierarchy(
|
|
82
|
-
return await this.schoolRepository.getUserContextDropdown();
|
|
81
|
+
async getOrganizationHierarchy(userId: number, appCode: string) {
|
|
82
|
+
return await this.schoolRepository.getUserContextDropdown(userId, appCode);
|
|
83
83
|
}
|
|
84
84
|
}
|
|
@@ -129,6 +129,7 @@ export class ModuleAccessService {
|
|
|
129
129
|
level_type: string;
|
|
130
130
|
level_id: number;
|
|
131
131
|
}) {
|
|
132
|
+
// Step 1: Resolve roles
|
|
132
133
|
const roleCodes = await this.menuRepository.resolveUserRoles(
|
|
133
134
|
userId,
|
|
134
135
|
appcode,
|
|
@@ -141,8 +142,34 @@ export class ModuleAccessService {
|
|
|
141
142
|
}
|
|
142
143
|
|
|
143
144
|
const roleIds = roleCodes.map(Number);
|
|
144
|
-
|
|
145
|
+
|
|
146
|
+
// Step 2: Get full permissions
|
|
147
|
+
const allPermissions = await this.moduleAccessRepository.getModuleAccessByRoles(
|
|
148
|
+
roleIds,
|
|
149
|
+
appcode,
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
// Step 3: If level_type is SCH, check school status using raw query
|
|
153
|
+
if (level_type === 'SCH') {
|
|
154
|
+
const result = await this.dataSource.query(
|
|
155
|
+
`SELECT * FROM cr_school WHERE id = ${level_id}`,
|
|
156
|
+
[level_id],
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
const school = result?.[0];
|
|
160
|
+
|
|
161
|
+
if (!school || school.status === "INACTIVE") {
|
|
162
|
+
// Return only VIEW permissions
|
|
163
|
+
return allPermissions.filter(
|
|
164
|
+
(perm) => perm.action === 'VIEW'
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Step 4: Return all permissions normally
|
|
170
|
+
return allPermissions;
|
|
145
171
|
}
|
|
146
172
|
|
|
147
173
|
|
|
174
|
+
|
|
148
175
|
}
|
|
@@ -44,4 +44,10 @@ export class UserData extends BaseEntity {
|
|
|
44
44
|
|
|
45
45
|
@Column({ type: 'varchar', nullable: true })
|
|
46
46
|
last_app_access: string;
|
|
47
|
+
|
|
48
|
+
@Column({ type: 'varchar', nullable: true })
|
|
49
|
+
last_level_type: string;
|
|
50
|
+
|
|
51
|
+
@Column({ type: 'varchar', nullable: true })
|
|
52
|
+
last_level_id: string;
|
|
47
53
|
}
|
|
@@ -59,25 +59,41 @@ export class LoginService {
|
|
|
59
59
|
};
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
|
|
63
|
-
const roleMappings = await this.userRoleMappingRepository.find({
|
|
64
|
-
where: {
|
|
65
|
-
user_id: user.id,
|
|
66
|
-
appcode: user.last_app_access,
|
|
67
|
-
},
|
|
68
|
-
});
|
|
62
|
+
let defaultAccess;
|
|
69
63
|
|
|
70
|
-
if (!
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
64
|
+
if (!user.last_level_type && !user.last_level_id) {
|
|
65
|
+
const roleMappings = await this.userRoleMappingRepository.find({
|
|
66
|
+
where: {
|
|
67
|
+
user_id: user.id,
|
|
68
|
+
appcode: user.last_app_access,
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
if (!roleMappings.length) {
|
|
73
|
+
throw new BadRequestException(
|
|
74
|
+
'User does not have any access mapped for this app.',
|
|
75
|
+
);
|
|
76
|
+
}
|
|
75
77
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
// ✅ Pick default access based on priority
|
|
79
|
+
const priority = { org: 1, sch: 2, brn: 3 };
|
|
80
|
+
defaultAccess = roleMappings.sort(
|
|
81
|
+
(a, b) => priority[a.level_type] - priority[b.level_type],
|
|
82
|
+
)[0];
|
|
83
|
+
|
|
84
|
+
if ((defaultAccess.level_type, defaultAccess.level_id)) {
|
|
85
|
+
await this.userService.setLastLevelTypeAndId(
|
|
86
|
+
user.id,
|
|
87
|
+
defaultAccess.level_type,
|
|
88
|
+
defaultAccess.level_id,
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
} else {
|
|
92
|
+
defaultAccess = {
|
|
93
|
+
level_type: user.last_level_type,
|
|
94
|
+
level_id: user.last_level_id,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
81
97
|
|
|
82
98
|
//appcode
|
|
83
99
|
|
|
@@ -85,8 +85,8 @@ export class UserSessionService {
|
|
|
85
85
|
};
|
|
86
86
|
|
|
87
87
|
await this.dataSource.query(
|
|
88
|
-
`UPDATE cr_user SET last_app_access = ? WHERE id = ?`,
|
|
89
|
-
[data.appcode, currentUser.id],
|
|
88
|
+
`UPDATE cr_user SET last_app_access = ? , last_level_type = ?, last_level_id = ? WHERE id = ?`,
|
|
89
|
+
[data.appcode, data.level_type, data.level_id, currentUser.id],
|
|
90
90
|
);
|
|
91
91
|
|
|
92
92
|
return {
|
|
@@ -249,4 +249,21 @@ export class UserService extends EntityServiceImpl {
|
|
|
249
249
|
|
|
250
250
|
await this.userRepository.saveUser(user); // This persists the updated field
|
|
251
251
|
}
|
|
252
|
+
|
|
253
|
+
async setLastLevelTypeAndId(
|
|
254
|
+
userId: number,
|
|
255
|
+
levelType: string,
|
|
256
|
+
levelId: string,
|
|
257
|
+
): Promise<void> {
|
|
258
|
+
const user = await this.userRepository.findById(userId);
|
|
259
|
+
|
|
260
|
+
if (!user) {
|
|
261
|
+
throw new BadRequestException('User not found');
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
user.last_level_type = levelType;
|
|
265
|
+
user.last_level_id = levelId;
|
|
266
|
+
|
|
267
|
+
await this.userRepository.saveUser(user); // This persists the updated field
|
|
268
|
+
}
|
|
252
269
|
}
|