🐛 运单列表按账号项目收口,避免查看其他账号数据
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+53
-33
@@ -152,7 +152,8 @@ public class WaybillServiceImpl extends BaseServiceImpl<WaybillMapper, Waybill>
|
||||
|
||||
@Override
|
||||
public WaybillVO detail(Long id) {
|
||||
WaybillVO result = WaybillWrapper.build().entityVO(syncDriverAcceptState(loadEditable(id, false)));
|
||||
Waybill loaded = syncDriverAcceptState(loadEditable(id, false));
|
||||
WaybillVO result = WaybillWrapper.build().entityVO(loaded);
|
||||
fillCustomerNameFromContract(result);
|
||||
fillCarrierContractName(List.of(result));
|
||||
fillMileageMaintainable(List.of(result));
|
||||
@@ -1328,21 +1329,7 @@ public class WaybillServiceImpl extends BaseServiceImpl<WaybillMapper, Waybill>
|
||||
LambdaQueryWrapper<Waybill> queryWrapper;
|
||||
if (Func.isNotEmpty(idList)) {
|
||||
queryWrapper = Wrappers.<Waybill>lambdaQuery().eq(Waybill::getIsDeleted, 0);
|
||||
List<Long> deptIdList = TransportBusinessSupport.resolveDeptFilterIds(
|
||||
waybill.getAllDept(), waybill.getDeptId(), "运单管理", TransportBusinessSupport.MENU_WAYBILL_MANAGE);
|
||||
if (Func.isNotEmpty(deptIdList)) {
|
||||
queryWrapper.and(wrapper -> {
|
||||
if (deptIdList.size() == 1) {
|
||||
wrapper.eq(Waybill::getDeptId, deptIdList.get(0));
|
||||
} else {
|
||||
wrapper.in(Waybill::getDeptId, deptIdList);
|
||||
}
|
||||
TransportBusinessSupport.orProjectVisibleByBusinessDept(wrapper, deptIdList);
|
||||
});
|
||||
}
|
||||
if (TransportBusinessSupport.isOwnCreateScope(TransportBusinessSupport.MENU_WAYBILL_MANAGE)) {
|
||||
queryWrapper.eq(Waybill::getCreateUser, AuthUtil.getUserId());
|
||||
}
|
||||
applyAccountScope(queryWrapper, waybill.getAllDept(), waybill.getDeptId());
|
||||
queryWrapper.in(Waybill::getId, idList).orderByDesc(Waybill::getCreateTime);
|
||||
} else {
|
||||
queryWrapper = buildQuery(waybill);
|
||||
@@ -1400,7 +1387,7 @@ public class WaybillServiceImpl extends BaseServiceImpl<WaybillMapper, Waybill>
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public WaybillVO copy(Long id) {
|
||||
Waybill source = loadEditable(id, true);
|
||||
Waybill source = loadEditable(id, false);
|
||||
Waybill target = new Waybill();
|
||||
target.setProjectId(source.getProjectId());
|
||||
target.setProjectName(source.getProjectName());
|
||||
@@ -1820,25 +1807,57 @@ public class WaybillServiceImpl extends BaseServiceImpl<WaybillMapper, Waybill>
|
||||
return loadingManageService.detail(loadingManage.getId());
|
||||
}
|
||||
|
||||
private LambdaQueryWrapper<Waybill> buildQuery(WaybillVO waybill) {
|
||||
LambdaQueryWrapper<Waybill> queryWrapper = Wrappers.<Waybill>lambdaQuery().eq(Waybill::getIsDeleted, 0);
|
||||
// 与常用线路等模块一致:超管默认不按组织过滤;普通用户 allDept!=1 时强制当前组织
|
||||
// 同时放行「所属项目业务部门」落在可见组织内的数据
|
||||
List<Long> deptIdList = TransportBusinessSupport.resolveDeptFilterIds(
|
||||
waybill.getAllDept(), waybill.getDeptId(), "运单管理", TransportBusinessSupport.MENU_WAYBILL_MANAGE);
|
||||
if (Func.isNotEmpty(deptIdList)) {
|
||||
queryWrapper.and(wrapper -> {
|
||||
if (deptIdList.size() == 1) {
|
||||
wrapper.eq(Waybill::getDeptId, deptIdList.get(0));
|
||||
} else {
|
||||
wrapper.in(Waybill::getDeptId, deptIdList);
|
||||
}
|
||||
TransportBusinessSupport.orProjectVisibleByBusinessDept(wrapper, deptIdList);
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 运单可见范围:超管不限制;普通账号仅本组织运单,以及归属本账号项目的运单。
|
||||
* 本人创建权限仍只看自己创建的运单。
|
||||
*/
|
||||
private void applyAccountScope(LambdaQueryWrapper<Waybill> queryWrapper, Integer allDept, Long deptId) {
|
||||
if (TransportBusinessSupport.isOwnCreateScope(TransportBusinessSupport.MENU_WAYBILL_MANAGE)) {
|
||||
queryWrapper.eq(Waybill::getCreateUser, AuthUtil.getUserId());
|
||||
return;
|
||||
}
|
||||
List<Long> deptIdList = TransportBusinessSupport.resolveScopedDeptFilterIds(
|
||||
allDept, deptId, "运单管理", TransportBusinessSupport.MENU_WAYBILL_MANAGE);
|
||||
if (Func.isEmpty(deptIdList)) {
|
||||
return;
|
||||
}
|
||||
Long currentUserId = AuthUtil.getUserId();
|
||||
queryWrapper.and(wrapper -> {
|
||||
if (deptIdList.size() == 1) {
|
||||
wrapper.eq(Waybill::getDeptId, deptIdList.get(0));
|
||||
} else {
|
||||
wrapper.in(Waybill::getDeptId, deptIdList);
|
||||
}
|
||||
TransportBusinessSupport.orProjectVisibleByBusinessDept(wrapper, deptIdList);
|
||||
TransportBusinessSupport.orProjectVisibleByAccount(wrapper, deptIdList, currentUserId);
|
||||
if (Func.isNotEmpty(currentUserId) && currentUserId > 0) {
|
||||
wrapper.or().eq(Waybill::getCreateUser, currentUserId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 详情、复制等按主键访问时复用列表可见范围,避免越权读取其他账号运单。
|
||||
*/
|
||||
private void assertWaybillVisible(Waybill waybill) {
|
||||
if (waybill == null || Func.isEmpty(waybill.getId())) {
|
||||
throw new ServiceException("运单管理不存在");
|
||||
}
|
||||
if (TransportBusinessSupport.isAdministrator()) {
|
||||
return;
|
||||
}
|
||||
WaybillVO probe = new WaybillVO();
|
||||
probe.setAllDept(0);
|
||||
LambdaQueryWrapper<Waybill> wrapper = buildQuery(probe);
|
||||
wrapper.eq(Waybill::getId, waybill.getId());
|
||||
if (count(wrapper) <= 0) {
|
||||
throw new ServiceException("无权查看该运单");
|
||||
}
|
||||
}
|
||||
|
||||
private LambdaQueryWrapper<Waybill> buildQuery(WaybillVO waybill) {
|
||||
LambdaQueryWrapper<Waybill> queryWrapper = Wrappers.<Waybill>lambdaQuery().eq(Waybill::getIsDeleted, 0);
|
||||
applyAccountScope(queryWrapper, waybill.getAllDept(), waybill.getDeptId());
|
||||
if (Func.isNotEmpty(waybill.getWaybillNo())) {
|
||||
queryWrapper.eq(Waybill::getWaybillNo, waybill.getWaybillNo());
|
||||
}
|
||||
@@ -2259,6 +2278,7 @@ public class WaybillServiceImpl extends BaseServiceImpl<WaybillMapper, Waybill>
|
||||
if (checkDept) {
|
||||
TransportBusinessSupport.assertCurrentDept(waybill.getDeptId(), "运单管理", TransportBusinessSupport.MENU_WAYBILL_MANAGE);
|
||||
}
|
||||
assertWaybillVisible(waybill);
|
||||
return waybill;
|
||||
}
|
||||
|
||||
|
||||
+48
@@ -286,6 +286,54 @@ public final class TransportBusinessSupport {
|
||||
return count != null && count > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 列表实际使用的组织范围。
|
||||
* <p>
|
||||
* 角色菜单未单独收窄、解析结果为「全部组织」时,超管仍不限制;
|
||||
* 普通用户在未显式请求全部组织(allDept != 1)时收口到当前组织,
|
||||
* 避免账号看到其他组织的业务数据。本人创建权限不按组织收口。
|
||||
*/
|
||||
public static List<Long> resolveScopedDeptFilterIds(Integer allDept, Long deptId, String moduleName, String menuCode) {
|
||||
List<Long> deptIdList = resolveDeptFilterIds(allDept, deptId, moduleName, menuCode);
|
||||
if (Func.isNotEmpty(deptIdList) || isAdministrator() || isOwnCreateScope(menuCode) || Objects.equals(allDept, 1)) {
|
||||
return deptIdList;
|
||||
}
|
||||
return Collections.singletonList(currentDeptId(moduleName));
|
||||
}
|
||||
|
||||
/**
|
||||
* 账号项目可见范围:承办部门命中指定组织,或当前用户是项目创建人、经办人、负责人。
|
||||
*/
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public static void orProjectVisibleByAccount(AbstractWrapper<?, ?, ?> wrapper, Collection<Long> deptIds, Long userId) {
|
||||
if (wrapper == null) {
|
||||
return;
|
||||
}
|
||||
List<Long> ids = deptIds == null ? List.of() : deptIds.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.filter(id -> id > 0)
|
||||
.distinct()
|
||||
.toList();
|
||||
if (!ids.isEmpty()) {
|
||||
if (ids.size() == 1) {
|
||||
wrapper.or().apply(
|
||||
"project_id IN (SELECT id FROM blade_project_apply WHERE is_deleted = 0 AND FIND_IN_SET({0}, IFNULL(undertake_dept_id,'')))",
|
||||
String.valueOf(ids.get(0)));
|
||||
} else {
|
||||
String undertakeSql = ids.stream()
|
||||
.map(id -> "FIND_IN_SET(" + id + ", IFNULL(undertake_dept_id,''))")
|
||||
.collect(Collectors.joining(" OR "));
|
||||
wrapper.or().apply(
|
||||
"project_id IN (SELECT id FROM blade_project_apply WHERE is_deleted = 0 AND (" + undertakeSql + "))");
|
||||
}
|
||||
}
|
||||
if (Func.isNotEmpty(userId) && userId > 0) {
|
||||
wrapper.or().apply(
|
||||
"project_id IN (SELECT id FROM blade_project_apply WHERE is_deleted = 0 AND (create_user = {0} OR handler_user_id = {0} OR principal_user_id = {0}))",
|
||||
userId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析列表组织筛选 ID。
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user