修改推送日志功能

This commit is contained in:
chenxing
2026-08-20 12:15:48 +08:00
parent db0d5e1a2d
commit 355920746b
5 changed files with 44 additions and 47 deletions
@@ -96,7 +96,8 @@ public class UserController {
*
* @param request 用于取 AppAuthFilter 设置的 appKey
* @param userId 用户ID(必填)
* @param schId 学校ID/组ID(可选;为 null 时按"主学校→主归属组"规则推断)
* @param schId 学校ID/组ID(可选;用于限定「学校上下文」:非空时仅取该学校子树内的真实归属组参与判定,
* 为空时取用户全部真实归属组,与权限一览一致)
* @return 该应用下用户已授权模块(扁平化;无权限时返回空列表)
*/
@GetMapping("modules")
@@ -38,6 +38,8 @@ public class SysOapiLogListVo {
private String operationDesc;
/** 请求参数JSON(脱敏后) */
private String requestParams;
/** 响应结果(GZIP 解压后原文,脱敏后;随列表带出,详情弹窗直接展示) */
private String responseData;
/** HTTP 状态码 */
private Integer statusCode;
/** 耗时(ms) */
@@ -1,9 +1,7 @@
package com.yunhai.userbase.service.impl;
import com.yunhai.platform.utils.exception.DException;
import com.yunhai.platform.utils.model.BoaGroup;
import com.yunhai.platform.utils.model.BoaModule;
import com.yunhai.platform.utils.model.BoaUser;
import com.yunhai.userbase.entity.*;
import com.yunhai.userbase.enums.GroupTypeEnum;
import com.yunhai.platform.utils.enums.IEnum;
@@ -104,9 +102,6 @@ public class GroupAuthzService implements IGroupAuthzService {
@Autowired
private SysUserAppRoleRelRepository sysUserAppRoleRelRepository;
@Autowired
private UserCenterService userCenterService;
// ===================== 新增:沿祖先链收集「本组+所有祖先组开通的应用ID并集」(应用池联动GetSchoolAppId)
// =====================
@@ -523,23 +518,43 @@ public class GroupAuthzService implements IGroupAuthzService {
}
// 3. 收集该用户启用角色下=属于目标应用的模块ID(角色授权并集,不要求组先开通应用)
Set<Integer> roleModuleIdsInApp = collectEnabledRoleModuleIdsForApp(userId, appId);
// 4. 上下文组解析(schId 非空=只认这一条链路;schId 空=按"主学校→主归属组"规则推断)
Integer effectiveGroupId = resolveEffectiveGroupId(userId, schId);
// 5. 若上下文组有效=构建其祖先链,并判定:该祖先链开通池里是否包含目标 appId(应用开通闸门)
// 上下文组无效(用户无学校/无组)时,仍可能因角色授权而返回模块,不能直接返回空
Set<Integer> selfGroupIds = new LinkedHashSet<>();
// 4. 归属组集合解析(与权限一览 findUserPermissionTree 语义对齐,修复"只返回学校节点"的 bug):
// - schId 非空:只取用户真实归属组中「位于该学校子树内」的组(含直接挂学校组本身),
// 每个组独立建链向上判定;子树内无任何归属组 → 保留空 selfGroupIds(方案A:仅靠角色授权拿模块,
// 不把 schId 冒充本组,否则会绕过子组继承闸门、丢本组数据);
// - schId 空:取用户全部真实归属组(与权限一览「用户全局模式」一致)。
List<SysUserGroupRel> userRels = sysUserGroupRelRepository.findByUserId(userId);
Map<Integer, SysGroup> allGroupMap = buildAllGroupMap();
Set<Integer> selfGroupIds = new LinkedHashSet<>();
if (schId != null) {
for (SysUserGroupRel rel : userRels) {
Integer gid = rel.getGroupId();
if (gid == null) {
continue;
}
if (gid.equals(schId) || ancestorChain(gid, allGroupMap).contains(schId)) {
selfGroupIds.add(gid);
}
}
} else {
for (SysUserGroupRel rel : userRels) {
if (rel.getGroupId() != null) {
selfGroupIds.add(rel.getGroupId());
}
}
}
// 5. 构建各归属组的祖先链与开通池,并判定:任意归属组开通池里是否包含目标 appId(应用开通闸门)。
// 归属组为空(该学校子树内无组 / 无学校无组)时仍可能因角色授权而返回模块,不能直接返回空。
Map<Integer, List<Integer>> chainMap = new HashMap<>();
Set<Integer> allChainIds = new LinkedHashSet<>();
Map<Integer, Set<Integer>> groupToApps = new HashMap<>();
boolean appOpened = false;
if (effectiveGroupId != null) {
selfGroupIds.add(effectiveGroupId);
List<Integer> chain = ancestorChain(effectiveGroupId, allGroupMap);
chainMap.put(effectiveGroupId, chain);
for (Integer gid : selfGroupIds) {
List<Integer> chain = ancestorChain(gid, allGroupMap);
chainMap.put(gid, chain);
allChainIds.addAll(chain);
Set<Integer> openedApps = collectAppIdsForAuthzScope(effectiveGroupId);
groupToApps.put(effectiveGroupId, openedApps);
Set<Integer> openedApps = collectAppIdsForAuthzScope(gid);
groupToApps.put(gid, openedApps);
if (openedApps.contains(appId)) {
appOpened = true;
}
@@ -612,33 +627,6 @@ public class GroupAuthzService implements IGroupAuthzService {
return result;
}
/**
* 上下文组解析(与开放接口 modules 语义严格一致):
* - schId 非空:直接用其作为唯一 selfGroupId;
* - schId 为空:取用户主学校组(BoaUser.school.id);
* - 仍空:取用户主归属组 id(groups 第 0 个);
* - 全空:返回 null(此时只能靠角色授权拿模块)。
*/
private Integer resolveEffectiveGroupId(Integer userId, Integer schId) {
if (schId != null) {
return schId;
}
BoaUser boa = userCenterService.getUserInfoWithDeptById(userId);
if (boa == null) {
return null;
}
BoaGroup school = boa.getSchool();
if (school != null && school.getId() != null) {
return school.getId();
}
List<BoaGroup> groups = boa.getGroups();
if (groups != null && !groups.isEmpty()) {
BoaGroup main = groups.get(0);
return main == null ? null : main.getId();
}
return null;
}
private static Map<Integer, AppModule> buildAppModuleMap(List<AppModule> appModules) {
Map<Integer, AppModule> map = new HashMap<>();
for (AppModule m : appModules) {
@@ -65,9 +65,9 @@ public class SysGroupService implements ISysGroupService {
// 区域组:只能挂在根节点下(由根节点的白名单约束),其下可挂 学段组/学校组/普通组
ALLOWED_CHILDREN.put(GroupTypeEnum.AREA_GROUP, EnumSet.of(
GroupTypeEnum.STAGE_GROUP, GroupTypeEnum.SCHOOL_GROUP, GroupTypeEnum.NORMAL_GROUP));
// 学段组(高中/初中/小学):学校组的上级,可含 学校组/普通组
// 学段组(高中/初中/小学):学校组的上级,可含 学校组/年级组
ALLOWED_CHILDREN.put(GroupTypeEnum.STAGE_GROUP, EnumSet.of(
GroupTypeEnum.SCHOOL_GROUP, GroupTypeEnum.NORMAL_GROUP));
GroupTypeEnum.SCHOOL_GROUP, GroupTypeEnum.GRADE_GROUP));
// 学校组:可含 教师组/学生组/普通组
ALLOWED_CHILDREN.put(GroupTypeEnum.SCHOOL_GROUP, EnumSet.of(
GroupTypeEnum.TEACHER_GROUP, GroupTypeEnum.STUDENT_GROUP, GroupTypeEnum.NORMAL_GROUP));
@@ -89,6 +89,10 @@ public class SysOapiLogServiceImpl implements ISysOapiLogService {
typed.setFirstResult((pageIndex - 1) * pageSize);
typed.setMaxResults(pageSize);
List<SysOapiLogListVo> content = typed.getResultList();
// 响应结果随列表带出(GZIP 解压后),供详情弹窗直接展示,无需再单独请求
for (SysOapiLogListVo vo : content) {
vo.setResponseData(getResponseData(vo.getId()));
}
int totalPages = (int) Math.ceil((double) total / pageSize);
boolean hasNext = pageIndex < totalPages;
@@ -165,9 +169,11 @@ public class SysOapiLogServiceImpl implements ISysOapiLogService {
}
if (StringUtils.isNotBlank(query.getKeyword())) {
String kw = "%" + query.getKeyword().trim() + "%";
// 单输入框同时匹配:请求路径(requestUri) / 应用名(callerAppName) / appKey(callerAppKey)
predicates.add(cb.or(
cb.like(root.get("requestUri"), kw),
cb.like(root.get("callerAppName"), kw)));
cb.like(root.get("callerAppName"), kw),
cb.like(cb.toString(root.get("callerAppKey")), kw)));
}
if (query.getStartTime() != null) {
predicates.add(cb.greaterThanOrEqualTo(root.get("createTime"), query.getStartTime()));