Files
flow-center-service/src/main/java/com/yunhai/flowcenter/service/FlowAccessGuard.java
T
chenxing 008aee3c88 [ysch-flow] S2.3 抄送接收人只读可见(F7 前置必修补丁)
requireInstanceVisible 此前只放行提交人/办理人/本校管理员,抄送接收人点开工作台
"抄送我的"行或抄送消息回落链接一律 403——"抄送中心自留、子应用零存储"因此不闭环。
新增 flw_cc 行命中判定(existsByInstanceIdAndUserId,按 instanceId 维度不泛化到本校),
只授予可见、办理权仍在 FlowTaskService 按 assigneeId 复核;中心用户面四处调用点
(详情/进度/出图)自动同口径。embed/url 签发侧 javadoc 同步可见性口径(oapi 层仍只认
schId,用户级判定在子应用后端,跨校与陌生人断言未放宽)。
守卫五态单测:提交人/办理人/管理员/抄送人/陌生人 + 抄送命中范围。
2026-10-17 23:01:01 +08:00

80 lines
3.7 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package com.yunhai.flowcenter.service;
import com.yunhai.flowcenter.entity.FlwInstance;
import com.yunhai.flowcenter.repository.FlwCcRepository;
import com.yunhai.flowcenter.repository.FlwTaskRepository;
import com.yunhai.platform.apistd.BizException;
import com.yunhai.platform.utils.exception.ErrorCode;
import com.yunhai.platform.utils.model.BoaUser;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.List;
/**
* 用户面访问守卫(概览 §十):提交人只读写自己办件;办理人只读写分派给自己的任务;
* 管理员本校可查、不可代批。
* 2026-10-17(F7 前置补丁):放行口径增「该办件 flw_cc 行接收人」——抄送接收人点开工作台
* "抄送我的"行或抄送消息回落链接此前一律 403,抄送自留因此不闭环。只读可见,办理权仍按 assigneeId。
* 管理员口径与 FlowAdminGuard / svc-hall ApplyViewGuard / Notice NoticeFlowGuard 对齐:
* type==1(超管)或 roleId∈{2,5,7}(校级管理员)——三者必须同口径,否则校级管理员
* 能列办件却在详情页 403(本类原先只认 type==1,2026-09-14 校正)。
*/
@Service
@RequiredArgsConstructor
public class FlowAccessGuard {
private static final int SUPER_ADMIN_TYPE = 1;
private static final List<Integer> ADMIN_ROLE_IDS = Arrays.asList(2, 5, 7);
private final FlwTaskRepository taskRepository;
private final FlwCcRepository ccRepository;
/** 办件详情可见:提交人本人 / 该办件任务办理人 / 本校管理员(超管或校级管理员)/ 该办件抄送接收人 */
public void requireInstanceVisible(FlwInstance instance, BoaUser user) {
if (user == null || user.getId() == null) {
throw new BizException(ErrorCode.FORBIDDEN, "未登录");
}
if (instance.getSubmitterId().equals(user.getId())) {
return;
}
if (!taskRepository.findByInstanceIdOrderByIdAsc(instance.getId()).stream()
.anyMatch(t -> user.getId().equals(t.getAssigneeId()))) {
// F7 前置补丁:抄送接收人可读(工作台"抄送我的"行与抄送消息回落链接不再 403)。
// 只授予可见,办理权仍在 FlowTaskService 按 assigneeId 复核。
if (!isCcRecipient(instance, user) && !isAdminOf(instance, user)) {
throw new BizException(ErrorCode.FORBIDDEN, "仅提交人/办理人/本校管理员可查看该办件");
}
}
}
/** 该用户是否本办件的抄送接收人(flw_cc 行,逐人一行) */
private boolean isCcRecipient(FlwInstance instance, BoaUser user) {
return ccRepository.existsByInstanceIdAndUserId(instance.getId(), user.getId());
}
/**
* 本校管理员(可查不可代批;办理权在 FlowTaskService 里再按 assigneeId 校验)。
* 超管与校级管理员均限本校——跨校仍 403,不放大可见范围。
*/
private boolean isAdminOf(FlwInstance instance, BoaUser user) {
Long current = currentSchId(user);
if (current == null || !current.equals(instance.getSchId())) {
return false;
}
if (user.getType() != null && user.getType() == SUPER_ADMIN_TYPE) {
return true;
}
return user.getRoleIds() != null
&& user.getRoleIds().stream().anyMatch(r -> r != null && ADMIN_ROLE_IDS.contains(r));
}
private Long currentSchId(BoaUser user) {
if (user.getCurrentRole() == null || user.getCurrentRole().getSchId() == null) {
return null;
}
return Long.valueOf(user.getCurrentRole().getSchId());
}
}