release: FL 2.0 候选(C01 记账边界+P2-2 认领协议+D10 变量契约+D11 资格终审+D09 激活代次+T01/T03/T04/T05)
按《FL最终代码审计与上线阻断清单》194 项已审计工作树形成候选,基座 = origin/main 11e0778。
- 源码/测试/资源:沿用已审计工作树内容(96 项相对远端为新增或更新),含未跟踪实现
CallbackFactStore、CallbackSourcePolicy、VariableContract、FormalApplyCommandService、
FlowActorContextGate 等;C01 续验夹具修正一并入内。
- CI:保留远端 11e0778 的门禁强化(CI_SOURCE_SHA 核对、容器回收验证、空 schema 反向门禁、
main ref 才推镜像);ci/flow-test-schema.sql 按当前实体重新生成(14→20 表,补 6 新表与
6 新列,回调日志复合唯一键 uk_flw_log_event_reg),workflow 表数断言同步 14→20。
- 依据:docs/tasks/evidence/FL-final-audit-20261027(194 项哈希/版本核对)。
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
package com.yunhai.flowcenter.service;
|
||||
|
||||
import com.yunhai.flowcenter.entity.FlwInstance;
|
||||
import com.yunhai.flowcenter.repository.FlwInstanceRepository;
|
||||
import com.yunhai.flowcenter.repository.FlwTaskRepository;
|
||||
import com.yunhai.platform.apistd.BizException;
|
||||
import com.yunhai.platform.utils.exception.ErrorCode;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/** Authenticated request scope; no user-supplied source/header is trusted. */
|
||||
@Component @RequiredArgsConstructor
|
||||
public class FlowOapiSourceScope implements HandlerInterceptor {
|
||||
private static final String ATTRIBUTE = FlowOapiSourceScope.class.getName();
|
||||
private final FlowSourcePrincipalResolver resolver;
|
||||
private final FlwInstanceRepository instances;
|
||||
private final FlwTaskRepository tasks;
|
||||
@Value("${flow-center.formal-command.enabled:false}") private boolean enabled;
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
|
||||
if (!enabled) return true;
|
||||
String source = resolver.resolve((String) request.getAttribute("yh.app.auth")).id;
|
||||
request.setAttribute(ATTRIBUTE, source);
|
||||
String id = request.getParameter("instanceId");
|
||||
java.util.regex.Matcher pathId = java.util.regex.Pattern.compile("/instance/(\\d+)(?:/|$)").matcher(request.getRequestURI());
|
||||
if (id == null && pathId.find()) id = pathId.group(1);
|
||||
String taskId = request.getParameter("taskId");
|
||||
java.util.regex.Matcher taskPath = java.util.regex.Pattern.compile("/task/(\\d+)(?:/|$)").matcher(request.getRequestURI());
|
||||
if (taskId == null && taskPath.find()) taskId = taskPath.group(1);
|
||||
if (id != null) requireOwn(parse(id), source);
|
||||
if (taskId != null) {
|
||||
Long task = parse(taskId);
|
||||
requireOwn(tasks.findById(task).orElseThrow(() -> denied()).getInstanceId(), source);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void requireOwn(Long id, String source) {
|
||||
FlwInstance instance = instances.findById(id).orElseThrow(() -> denied());
|
||||
if (!source.equals(instance.getSourcePrincipalId())) throw denied();
|
||||
}
|
||||
|
||||
public static String current() {
|
||||
String source = currentOr(null);
|
||||
if (source == null) throw denied();
|
||||
return source;
|
||||
}
|
||||
public static String currentOr(String fallback) {
|
||||
if (!(RequestContextHolder.getRequestAttributes() instanceof ServletRequestAttributes)) return fallback;
|
||||
Object value = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getAttribute(ATTRIBUTE);
|
||||
return value instanceof String ? (String) value : fallback;
|
||||
}
|
||||
private Long parse(String value) {
|
||||
try { return Long.valueOf(value); } catch (NumberFormatException e) { throw denied(); }
|
||||
}
|
||||
private static BizException denied() { return new BizException(ErrorCode.FORBIDDEN, "仅允许访问本应用来源的流程事实"); }
|
||||
}
|
||||
Reference in New Issue
Block a user