package jnpf.bizcommon.onlyoffice.entity;
|
|
import lombok.Data;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.stereotype.Component;
|
|
import java.util.ArrayList;
|
import java.util.LinkedHashMap;
|
import java.util.List;
|
import java.util.Map;
|
|
/**
|
* OnlyOffice 集成参数,绑定 {@code config/shared/jnpf-biz-common.yaml} 的 {@code onlyoffice.*}。
|
*
|
* <p>三个 base url 之所以分开而不是共用一个「网关地址」,是因为它们的**视角不同**:
|
* {@code dsPublicUrl} 是浏览器视角(容器名浏览器解析不了),另两个是 DS 容器视角。
|
* 宿主 java -jar 栈下后两者要覆盖成 host.docker.internal(DS 在容器、网关在宿主)。
|
*/
|
@Data
|
@Component
|
@ConfigurationProperties(prefix = "onlyoffice")
|
public class OnlyOfficeProperties {
|
|
/** 浏览器加载编辑器 api.js 的地址,如 http://localhost:20000 */
|
private String dsPublicUrl;
|
|
/** DS 回源拉原始文档的网关地址,如 http://cx-gateway:30000 */
|
private String fileFetchBaseUrl;
|
|
/** DS 回调后端的网关地址,如 http://cx-gateway:30000 */
|
private String callbackBaseUrl;
|
|
/**
|
* 后端反向拉取 DS 产物的地址(后端视角),如 http://cx-onlyoffice。
|
*
|
* <p>保存回调里 DS 给的下载 url 用的是**它自己视角**的主机名,后端不一定能直连;
|
* 配了本项就只保留其 path+query 换到这个主机上。留空则原样使用 DS 给的 url。
|
*/
|
private String dsInternalUrl;
|
|
/**
|
* 与 DS 容器 JWT_SECRET 同源。后端用它签发编辑器 config,并校验 DS 回调的
|
* Authorization 头。回调端点在网关白名单内(平台补丁 #9),此密钥是其唯一安全边界。
|
*/
|
private String jwtSecret;
|
|
/** 编辑锁心跳超时(分钟)。锁正常由 status 2/4 回调释放,此项是浏览器崩溃等异常场景的兜底 */
|
private Integer lockTimeoutMinutes = 30;
|
|
/**
|
* 是否允许在编辑器里下载文档(对应「文件 → 下载为」与顶栏右侧的下载图标)。
|
*
|
* <p>默认关闭。⚠️ 它只收界面入口,不是安全边界——{@code /api/file/Image/**} 在网关白名单内、
|
* 只靠 securityKey 票据鉴权,知道 URL 的人照样能取到原文件。
|
*/
|
private boolean allowDownload = false;
|
|
/** 是否允许在编辑器里打印(对应「文件 → 打印」与顶栏右侧的打印图标)。默认关闭,同上注意事项 */
|
private boolean allowPrint = false;
|
|
/** 编辑权限判定,见 {@link EditPermission} */
|
private EditPermission editPermission = new EditPermission();
|
|
/** ONLYOFFICE 插件注册表与场景绑定 */
|
private Plugins plugins = new Plugins();
|
|
@Data
|
public static class Plugins {
|
|
/** 插件编码到部署定义的映射 */
|
private Map<String, PluginDefinition> definitions = new LinkedHashMap<>();
|
|
/** 允许启用插件的业务场景 */
|
private List<PluginSceneMapping> scenes = new ArrayList<>();
|
}
|
|
@Data
|
public static class PluginDefinition {
|
|
/** 与插件 config.json 完全一致的 GUID */
|
private String guid;
|
|
/** 插件契约版本 */
|
private String version;
|
|
/** 浏览器可访问的插件资源基础地址,不含 release */
|
private String publicBaseUrl;
|
|
/** 不可变发布目录;正式版本为 0.1.0 */
|
private String release = "0.1.0";
|
|
/** 浏览器可访问的插件业务 API 基础地址 */
|
private String apiBaseUrl;
|
}
|
|
@Data
|
public static class PluginSceneMapping {
|
|
private String bizScene;
|
|
private String bizModule;
|
|
private List<String> pluginCodes = new ArrayList<>();
|
|
/** 打开编辑器后自动启动的插件编码,必须属于 pluginCodes */
|
private String autostartPluginCode;
|
|
/** 当前场景需要禁用的 Document Server 内置插件 GUID */
|
private List<String> disabledPluginGuids = new ArrayList<>();
|
}
|
|
/**
|
* 「谁能编辑」的判定规则。
|
*
|
* <p>粒度是**菜单/按钮级**,与平台在线表单的单条更新端点一致
|
* ({@code VisualdevModelDataController#update} 只做 {@code StpUtil.checkPermission})。
|
* 判定所需的权限码在登录时就已灌进 Sa-Token 会话,纯本地判断、零 Feign 调用。
|
*
|
* <p>为什么不做「记录级」(这一条检验单该不该给这个人改):那属于业务规则,
|
* 依赖业务表字段(班组、负责人、流程状态),而 biz-common 的准入规则禁止它含单一
|
* 业务模块的专属逻辑。需要记录级时应由业务模块自行判定后再打开编辑器。
|
*/
|
@Data
|
public static class EditPermission {
|
|
/**
|
* 未登记的 bizModule(或请求根本没带 bizModule)时的取向。
|
*
|
* <p>{@code false}(默认)= 放行编辑,只打一条 warn 日志。这是**兼容默认值**:
|
* 里程碑 3 的最简调用 {@code openOfficeDocument({ file })} 并不传 bizModule,
|
* 一上来就严格会让所有既有调用方突然变只读。
|
*
|
* <p>{@code true} = 一律只读。业务侧把该登记的都登记完之后应当打开它——
|
* 否则「配置漏登记」这种失误会表现为「悄悄放行编辑」,而不是被人察觉的报错。
|
*/
|
private boolean strict = false;
|
|
/**
|
* bizModule → 在线表单 moduleId 的登记表。
|
*
|
* <p>刻意用 List 而不是 Map:Spring Boot Binder 对 Map 是**合并**语义、对 List 是
|
* **整体替换**,用 Map 的话删掉一条登记根本不生效(audit 的 layer0 注册表踩过这个坑,
|
* 见 {@code AuditFormRegistry})。
|
*/
|
private List<ModuleMapping> modules = new ArrayList<>();
|
}
|
|
@Data
|
public static class ModuleMapping {
|
|
/** 调用方传来的业务模块标识,与 {@code OnlyOfficeConfigParam.bizModule} 对应 */
|
private String bizModule;
|
|
/** 对应的在线表单功能主键(base_module.f_id),权限码就是拿它拼的 */
|
private String moduleId;
|
|
/**
|
* 是否要求 {@code moduleId::btn_edit} 按钮权限,默认 true。
|
*
|
* <p>⚠️ 这条是个陷阱位:在线表单只有勾了「启用按钮权限」时,用户的权限表里才会有
|
* {@code moduleId::btn_edit}。没启用却把本项留成 true,会导致**所有人都被降级只读**。
|
* 该模块没启用按钮权限时填 false,此时只校验菜单级权限。
|
*/
|
private boolean requireBtnEdit = true;
|
}
|
}
|