package jnpf.flowable.util.filepermission;
|
|
import jnpf.flowable.model.filepermission.FilePermissionPolicy.Action;
|
import jnpf.flowable.model.filepermission.FilePermissionPolicy.Effect;
|
import jnpf.flowable.model.filepermission.FilePermissionPolicy.Rule;
|
import java.util.*;
|
|
/**
|
* 纯规则裁决。调用方必须先按真实实例、执行轮次、人员关系解析适用规则。
|
* 不可直接将请求中的规则、版本、人员或布尔权限传入作为可信授权。
|
*/
|
public final class FilePermissionEvaluator {
|
private FilePermissionEvaluator() { }
|
|
public static final class Result {
|
public final long version;
|
public final Map<Action, Boolean> actions;
|
/** 原因保留到规则 ID;不返回其他参与人的身份。 */
|
public final Map<Action, String> reasons;
|
|
private Result(long version, Map<Action, Boolean> actions, Map<Action, String> reasons) {
|
this.version = version;
|
this.actions = Collections.unmodifiableMap(actions);
|
this.reasons = Collections.unmodifiableMap(reasons);
|
}
|
}
|
|
public static Result evaluate(String formId, String field, long version, boolean transitioning,
|
Map<Action, Boolean> nativeUpperBound, Map<Action, Boolean> inherited,
|
Collection<Rule> applicableRules) {
|
Objects.requireNonNull(formId, "formId");
|
Objects.requireNonNull(field, "field");
|
Objects.requireNonNull(nativeUpperBound, "nativeUpperBound");
|
Objects.requireNonNull(inherited, "inherited");
|
Objects.requireNonNull(applicableRules, "applicableRules");
|
if (version < 0) throw new IllegalArgumentException("权限版本无效");
|
Map<Action, Boolean> actions = new EnumMap<>(Action.class);
|
Map<Action, String> reasons = new EnumMap<>(Action.class);
|
for (Action action : Action.values()) {
|
boolean allow = Boolean.TRUE.equals(inherited.get(action));
|
String deniedBy = null;
|
for (Rule rule : applicableRules) {
|
if (!formId.equals(rule.formId) || !field.equals(rule.field)) continue;
|
Effect effect = rule.actions.get(action);
|
if (effect == Effect.DENY) {
|
// 顺序不影响裁决和返回原因,便于缓存/审计一致性。
|
if (deniedBy == null || rule.id.compareTo(deniedBy) < 0) deniedBy = rule.id;
|
} else if (effect == Effect.ALLOW) allow = true;
|
}
|
String reason = transitioning ? "TRANSITIONING" : !Boolean.TRUE.equals(nativeUpperBound.get(action))
|
? "NATIVE_PERMISSION" : deniedBy != null ? "RULE:" + deniedBy : !allow ? "INHERITED_DENY" : null;
|
actions.put(action, reason == null);
|
if (reason != null) reasons.put(action, reason);
|
}
|
return new Result(version, actions, reasons);
|
}
|
}
|